2010-12-17 27 views
4

我想要一個NSRegularExpression的– stringByReplacingMatchesInString:options:range:withTemplate:方法的變體,它採用一個塊而不是模板。塊的返回值將被用作重置值。如你所想,這比模板更靈活。有點像在Perl正則表達式中使用/e修飾符。這是一個理智的Objective-C塊實現嗎?

所以我寫了一個類添加方法。這是我想出了:

@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 

這是我第一次在目的C.玩積木的嘗試,感覺有點怪異,但它似乎運作良好。我有幾個關於它的問題,但:

  1. 這似乎是一個理智的方式來實現這樣的方法嗎?
  2. 有沒有一些方法可以使用-enumerateMatchesInString:options:range:usingBlock: 來實現它的內部?我試過了,但是不能從塊內分配到pos。但是如果有辦法讓它工作,那麼也可以通過NSMatchingFlags和BOOL來處理它們,就像那個方法一樣。 DO-能?

更新

感謝來自Dave德隆的回答,我已經使用了塊新版本:

@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 

偉大的作品,謝謝!

+0

這真的很方便。謝謝! – 2012-08-09 10:07:28

回答

6

能夠從該塊內分配給pos會從改變聲明一樣簡單:

NSUInteger pos = 0; 

要:

__block NSUInteger pos = 0; 

__block關鍵字更多信息:__block Variables

+2

完全合理,「戴夫說了些什麼」。 :) – bbum 2010-12-18 00:09:37

+0

真棒,謝謝!我將使用塊更新新版本的問題。 – theory 2010-12-18 00:33:18

相關問題