用 NSAttributedString 中的图片替换微笑

Replace smiles with images in NSAttributedString

我有一个 Emoji 实体列表,每个实体都有 属性 codes,我想检查字符串 ("]:-)") 是否包含其中任何一个然后用图片替换微笑。

for (Emoji *emoji in self.emojis) {
    for (NSString *code in emoji.codes) {
        NSString *pattern = [NSRegularExpression escapedPatternForString:code];
        NSRegularExpression *regex = [[NSRegularExpression alloc] initWithPattern:pattern options:0 error:nil];

        NSArray *matches = [regex matchesInString:[sourceString string] options:0 range:NSMakeRange(0, [sourceString length])];

        [matches enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(NSTextCheckingResult * _Nonnull aResult, NSUInteger idx, BOOL * _Nonnull stop) {
            NSTextAttachment *attachment = [[NSTextAttachment alloc] init];
            [attachment setImage:[UIImage imageNamed:emoji.image]];

            NSAttributedString *replacement = [NSAttributedString attributedStringWithAttachment:attachment];
            [sourceString replaceCharactersInRange:[aResult range] withAttributedString:replacement];
        }];
    }
}

问题是 smile with code ]:-) 包含 :-) 而我的方法将其替换为下一个: bracket ] + [image] 对于 :-),这是因为 :-) 在列表中排在第一位。

如何检查准确的字符串?

我试过: ]:-/)\b]:-/)\b/^]:-/)$/

也许有更好的解决方案可以使它正常工作。

如果我理解正确你当前的结构:

@interface Emoji : NSObject
@property (nonatomic, strong) NSString *image; //I'd expect a UIImage there and not an image name
@property (nonatomic, strong) NSArray *codes;
@end

一个可能的解决方案是使用一对值:imageName/code

@interface Emoji : NSObject
@property (nonatomic, strong) NSString *image; //I'd expect a UIImage there and not an image name
@property (nonatomic, strong) NSString *code;
@end

self.emojis 将有大量 Emoji 对象,它们可能对不同的代码具有相同的图像名称,但这样做的一个好处是这个小技巧:
以 "smaller" 个表情符号排在末尾的方式对 self.emojis 进行排序。因此,您将首先仅替换 "lengthy" 和较小的。

self.emojis = [arrayOfSingleEmojis sortedArrayUsingComparator:^NSComparisonResult(Emoji * _Nonnull emoji1, Emoji * _Nonnull emoji2) {
    NSUInteger length1 = [[emoji1 code] length];
    NSUInteger length2 = [[emoji2 code] length];
    return [@(length2) compare:@(length1)]; //Or reverse length1 & length2, I never know, I always have to test, but I think it's the correct one
}];

因此在您当前的情况下:]:-) 将在 :-) 之前被替换,因此您应该使用 <imageFor:">:-)"] 而不是 ]<imageFor:":-)>