【问题标题】:Is this a sane Objective-C Block Implementation?这是一个理智的 Objective-C 块实现吗?
【发布时间】:2011-09-16 02:52:18
【问题描述】:

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

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

@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 中玩积木。感觉有点奇怪,但似乎效果很好。不过,我有几个问题:

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

更新

感谢 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

效果很好,谢谢!

【问题讨论】:

  • 这真的很方便。谢谢!

标签: objective-c objective-c-blocks objective-c-category


【解决方案1】:

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

NSUInteger pos = 0;

收件人:

__block NSUInteger pos = 0;

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

【讨论】:

  • 完全合理和“戴夫所说的”。 :)
  • 太棒了,谢谢!我将使用块更新新版本的问题。
猜你喜欢
  • 1970-01-01
  • 2010-10-19
  • 1970-01-01
  • 1970-01-01
  • 2013-03-25
  • 1970-01-01
  • 2019-03-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多