将目标字符串中的正则表达式匹配替换为Objective-C中的图像

mic*_*den 2 objective-c nsattributedstring nsregularexpression nsmutableattributedstring

我的目标是在Parse.com中存储属性字符串的信息.我决定为我的图像提供一个属性文本的编码,通过用{X}相应的图像替换大括号中的任何字符串来工作.例如:

Picture of 2 colorless mana: {X}
Run Code Online (Sandbox Code Playgroud)

应该生成一个{X}由图像替换的属性字符串.这就是我尝试过的:

NSString *formattedText = @"This will cost {2}{PW}{PW} to cast.";
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"(?<=\\{)[^}]+(?=\\})" options:NSRegularExpressionAnchorsMatchLines
                                                                         error:nil];
NSArray *matches = [regex matchesInString:formattedText
                                  options:kNilOptions
                                    range:NSMakeRange(0, formattedText.length)];
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:formattedText];
for (NSTextCheckingResult *result in matches)
{
    NSString *match = [formattedText substringWithRange:result.range];
    NSTextAttachment *imageAttachment = [NSTextAttachment new];
    imageAttachment.image = [UIImage imageNamed:[NSString stringWithFormat:@"Mana%@.png", match]];
    NSAttributedString *replacementForTemplate = [NSAttributedString attributedStringWithAttachment:imageAttachment];
    [attributedString replaceCharactersInRange:result.range
                          withAttributedString:replacementForTemplate];
}
[_textView setAttributedText:attributedString];
Run Code Online (Sandbox Code Playgroud)

目前这种方法存在两个问题:

  • 大括号不会被替换,只会替换它们内部的文本.
  • 每个匹配的范围都在变化,因为字符串本身正在发生变化,并且每个替换的原始文本长度> 1时,它会变得更多.这是它的样子:

图片http://i57.tinypic.com/idgeqh.png

Jos*_*ell 7

两个问题:

大括号不会被替换.那是因为你正在使用断言,这些断言不算作比赛的一部分.您使用模式进行的匹配仅包含大括号内的内容.改为使用此模式:

\{([^}]+)\}
Run Code Online (Sandbox Code Playgroud)

那就是:匹配一个大括号,然后是一个或多个没有关闭捕获组中大括号的东西,然后是一个右大括号.整个比赛现在包括括号.

这引入了另一个问题 - 你使用封闭的位来挑选替换图像.解决此问题的小改动:内部捕获组现在拥有该信息,而不是整个组.捕获组的长度告诉您所需子字符串的范围.

NSUInteger lengthOfManaName = [result rangeAtIndex:1].length;
NSString manaName = [match substringWithRange:(NSRange){1, lengthOfManaName}];
imageAttachment.image = [UIImage imageNamed:[NSString stringWithFormat:@"Mana%@.png", manaName]];
Run Code Online (Sandbox Code Playgroud)

第二个问题:字符串的长度在变化.向后列举:

for (NSTextCheckingResult *result in [matches reverseObjectEnumerator])
{
    //...
}
Run Code Online (Sandbox Code Playgroud)

现在,对字符串末尾的范围的更改不会影响早期范围.