2010-12-17 2 views
4

템플릿 대신 블록을 사용하는 변형 NSRegularExpression의 – stringByReplacingMatchesInString:options:range:withTemplate: 메서드가 필요했습니다. 블록의 반환 값은 대체 값으로 사용됩니다. 상상할 수 있듯이 이것은 템플릿보다 유연합니다. Perl 정규 표현식에서 /e 수정자를 사용하는 것과 같습니다.이것은 목표 -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을 전달하고 그 메소드와 같은 방식으로 처리하는 것이 좋습니다. 할 수 있는? 데이브 드롱의 대답

업데이트

덕분에, 나는 블록을 사용하여 새로운 버전을 가지고 :

@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

정말 편리합니다. 고맙습니다! –

답변

6

에서 선언을 변경하는 것처럼 간단 할 것이다 블록 내에서 pos에 할당 할 수 있다는 :

NSUInteger pos = 0; 

사람 :

__block NSUInteger pos = 0; 
__block 키워드

더 많은 정보 : __block Variables

+2

완벽하게 합리적인 "Dave의 말". :) – bbum

+0

굉장, 고마워! 블록을 사용하여 새 버전으로 질문을 업데이트하겠습니다. – theory