问题描述
我想要一个NSRegularExpression的– stringByReplacingMatchesInString:options:range:withTemplate:
方法的变体,它采用一个块而不是一个模板.该块的返回值将用作替换值.可以想象,这比模板更灵活.有点像在Perl正则表达式中使用/e
修饰符.
I wanted a variation of NSRegularExpression's – stringByReplacingMatchesInString:options:range:withTemplate:
method that takes a block instead of a template. The return value of the block would be used as the replacement value. This is more flexible than a template, as you can imagine. Sort of like using the /e
modifier in Perl regular expressions.
所以我写了一个类别来添加方法.这是我想出的:
So I wrote a category to add the method. This is what I came up with:
@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中玩积木.感觉有点奇怪,但似乎效果很好.我对此有几个疑问:
This is my first attempt to play with blocks in Objective C. It feels a little weird, but it seems to work well. I have a couple of questions about it, though:
- 这似乎是实施这种方法的明智方法吗?
- 是否有某种方法可以使用
-enumerateMatchesInString:options:range:usingBlock:
来实现其内部?我尝试过,但是无法从该块内分配给pos
.但是,如果有一种方法可以使它起作用,那么也可以传递NSMatchingFlags和BOOL并以与该方法相同的方式处理它们,这很酷.可以吗?
- Does this seem like a sane way to implement such a method?
- Is there some way to implement its internals using
-enumerateMatchesInString:options:range:usingBlock:
? I tried it, but could not assign topos
from within the block. But if there was a way to make it work, it'd be cool to also pass the NSMatchingFlags and BOOL and handle them in the same way as that method. Do-able?
更新
感谢戴夫·德隆(Dave DeLong)的回答,我使用了一个新的代码块:
Thanks to the answer from Dave DeLong, I've got a new version using a block:
@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
太棒了,谢谢!
推荐答案
能够从块内分配给pos
就像将声明从以下位置更改一样简单:
Being able to assign to pos
from within the block would be as simple as changing the declaration from:
NSUInteger pos = 0;
收件人:
__block NSUInteger pos = 0;
有关__block
关键字的更多信息: __block
变量
More info on the __block
keyword: __block
Variables
这篇关于这是合理的Objective-C块实现吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!