Skip to content

Instantly share code, notes, and snippets.

@rickytan
Created January 18, 2019 04:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rickytan/a2906fc6ecc882f4788f853591b67574 to your computer and use it in GitHub Desktop.
Save rickytan/a2906fc6ecc882f4788f853591b67574 to your computer and use it in GitHub Desktop.
NSString regular expression replace
@interface NSString (RegExp)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wstrict-prototypes"
- (NSString *)reg_replace:(NSRegularExpression *)regexp withBlock:(NSString *(NS_NOESCAPE ^)())block;
- (NSString *)reg_replacePattern:(NSString *)pattern withBlock:(NSString *(NS_NOESCAPE ^)())block;
#pragma clang diagnostic pop
@end
#import "NSString+RegExp.h"
FOUNDATION_EXTERN bool _Block_has_signature(id);
FOUNDATION_EXTERN const char * _Block_signature(id);
@implementation NSString (RegExp)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wstrict-prototypes"
- (NSString *)reg_replacePattern:(NSString *)pattern withBlock:(NSString *(NS_NOESCAPE ^)())block
{
return [self reg_replace:[NSRegularExpression regularExpressionWithPattern:pattern
options:0
error:NULL]
withBlock:block];
}
- (NSString *)reg_replace:(NSRegularExpression *)regexp withBlock:(NSString *(NS_NOESCAPE ^)())block
#pragma clang diagnostic pop
{
NSParameterAssert(regexp);
NSParameterAssert(block);
NSParameterAssert(_Block_has_signature(block));
__block NSMutableString *newString = [NSMutableString stringWithCapacity:self.length];
__block NSUInteger offset = 0;
[regexp enumerateMatchesInString:self
options:0
range:NSMakeRange(0, self.length)
usingBlock:^(NSTextCheckingResult * _Nullable result, NSMatchingFlags flags, BOOL * _Nonnull stop) {
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[NSMethodSignature signatureWithObjCTypes:_Block_signature(block)]];
NSUInteger numberOfArguments = invocation.methodSignature.numberOfArguments;
[invocation setTarget:[block copy]];
__autoreleasing NSString *string = self;
[invocation setArgument:&string atIndex:1];
NSRange range = result.range;
[invocation setArgument:&range atIndex:2];
string = [self substringWithRange:range];
[invocation setArgument:&string atIndex:3];
NSUInteger count = MIN([result numberOfRanges], numberOfArguments - 3);
for (NSUInteger i = 1; i < count; ++i) {
NSRange range = [result rangeAtIndex:i];
NSString *substr = [self substringWithRange:range];
[invocation setArgument:&substr atIndex:i + 3];
}
[invocation invoke];
[invocation getReturnValue:&string];
[newString appendString:[self substringWithRange:NSMakeRange(offset, range.location - offset)]];
[newString appendString:string];
offset = range.location + range.length;
}];
[newString appendString:[self substringWithRange:NSMakeRange(offset, self.length - offset)]];
return newString;
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment