这是一个理智的Objective-C Block实现吗?

the*_*ory 4 objective-c objective-c-blocks objective-c-category

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

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

@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
Run Code Online (Sandbox Code Playgroud)

这是我第一次尝试使用Objective C中的块.感觉有点奇怪,但似乎运行良好.不过,我有几个问题:

  1. 这看起来像是实现这种方法的理智方式吗?
  2. 有没有办法实现其内部使用-enumerateMatchesInString:options:range:usingBlock: ?我尝试过,但无法pos从块中分配.但是如果有一种方法可以使它工作,那么传递NSMatchingFlags和BOOL并以与该方法相同的方式处理它们也会很酷.DO-能?

更新

感谢Dave DeLong的回答,我有一个使用块的新版本:

@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
Run Code Online (Sandbox Code Playgroud)

工作得很好,谢谢!

Dav*_*ong 6

能够pos从块内分配将像更改声明一样简单:

NSUInteger pos = 0;
Run Code Online (Sandbox Code Playgroud)

至:

__block NSUInteger pos = 0;
Run Code Online (Sandbox Code Playgroud)

关于这个__block关键词的更多信息: __block变量

  • 完全合理,"戴夫说什么".:) (2认同)