这是合理的Objective-C块实现吗? [英] Is this a sane Objective-C Block Implementation?

查看:115
本文介绍了这是合理的Objective-C块实现吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要一个NSRegularExpression的– stringByReplacingMatchesInString:options:range:withTemplate:方法的变体,它采用一个块而不是一个模板.该块的返回值将用作替换值.可以想象,这比模板更灵活.有点像在Perl正则表达式中使用/e修饰符.

I wanted a variation of NSRegularExpression's – stringByReplacingMatchesInString:options:range:withTemplate: method that takes a block instead of a template. The return value of the block would be used as the replacement value. This is more flexible than a template, as you can imagine. Sort of like using the /e modifier in Perl regular expressions.

所以我写了一个类别来添加方法.这是我想出的:

So I wrote a category to add the method. This is what I came up with:

@implementation NSRegularExpression (Block)

- (NSString *)stringByReplacingMatchesInString:(NSString *)string
                                       options:(NSMatchingOptions)options
                                         range:(NSRange)range
                                    usingBlock:(NSString* (^)(NSTextCheckingResult *result))block
{
    NSMutableString *ret = [NSMutableString string];
    NSUInteger pos = 0;

    for (NSTextCheckingResult *res in [self matchesInString:string options:options range:range]) {
        if (res.range.location > pos) {
            [ret appendString:[string substringWithRange:NSMakeRange(pos, res.range.location - pos)]];
        }
        pos = res.range.location + res.range.length;
        [ret appendString:block(res)];
    }
    if (string.length > pos) {
        [ret appendString:[string substringFromIndex:pos]];
    }
    return ret;
}

@end

这是我第一次尝试在Objective C中玩积木.感觉有点奇怪,但似乎效果很好.我对此有几个疑问:

This is my first attempt to play with blocks in Objective C. It feels a little weird, but it seems to work well. I have a couple of questions about it, though:

  1. 这似乎是实施这种方法的明智方法吗?
  2. 是否有某种方法可以使用-enumerateMatchesInString:options:range:usingBlock: 来实现其内部?我尝试过,但是无法从该块内分配给pos.但是,如果有一种方法可以使它起作用,那么也可以传递NSMatchingFlags和BOOL并以与该方法相同的方式处理它们,这很酷.可以吗?
  1. Does this seem like a sane way to implement such a method?
  2. Is there some way to implement its internals using -enumerateMatchesInString:options:range:usingBlock: ? I tried it, but could not assign to pos from within the block. But if there was a way to make it work, it'd be cool to also pass the NSMatchingFlags and BOOL and handle them in the same way as that method. Do-able?


更新

感谢戴夫·德隆(Dave DeLong)的回答,我使用了一个新的代码块:

Thanks to the answer from Dave DeLong, I've got a new version using a block:

@implementation NSRegularExpression (Block)

- (NSString *)stringByReplacingMatchesInString:(NSString *)string
                                       options:(NSMatchingOptions)options
                                         range:(NSRange)range
                                    usingBlock:(NSString * (^)(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop))block
{
    NSMutableString *ret = [NSMutableString string];
    __block NSUInteger pos = 0;

    [self enumerateMatchesInString:string options:options range:range usingBlock:^(NSTextCheckingResult *match, NSMatchingFlags flags, BOOL *stop)
    {
        if (match.range.location > pos) {
            [ret appendString:[string substringWithRange:NSMakeRange(pos, match.range.location - pos)]];
        }
        pos = match.range.location + match.range.length;
        [ret appendString:block(match, flags, stop)];
    }];
    if (string.length > pos) {
        [ret appendString:[string substringFromIndex:pos]];
    }
    return [NSString stringWithString:ret];
}

@end

太棒了,谢谢!

推荐答案

能够从块内分配给pos就像将声明从以下位置更改一样简单:

Being able to assign to pos from within the block would be as simple as changing the declaration from:

NSUInteger pos = 0;

收件人:

__block NSUInteger pos = 0;

有关__block关键字的更多信息:

More info on the __block keyword: __block Variables

这篇关于这是合理的Objective-C块实现吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆