繁体   English   中英

属性文本,使用swift将一种特定的字体替换为另一种

[英]Attributed text, replace a specific font by another using swift

我在UITextView中使用属性文本。 文本包含许多字体。

我正在寻找一种将另一种字体替换为另一种字体的方法。

有什么快速的方法吗? :)

有一个称为attributesAtIndex(_:effectiveRange:) 此方法返回一个字典,您可以从中获取字体。

您将需要遍历每个索引来存储字体。 这会很慢,因为在文本文件中,字体可能会更改每个字符。 因此,我建议在主线程之外执行此操作。

我的代码将在Objective-C中进行,但是由于我们同时使用了CocoaTouch,因此逻辑应该相同。

我使用的方法是enumerateAttribute:inRange:options:usingBlock:仅查找NSFontAttributeName

还有一点没有讨论:如何识别字体是搜索到的字体。 您是否要查找familyNamefontNameUIFont属性?即使在同一个家族中,字体看起来也可能有很大不同,并且您可能想真正地搜索完全匹配相同名称的字体。我在这里曾经讨论过Font Names。您可能会发现这种情况很有趣,请注意,有些方法(当时我还不知道)可以获取字体的粗体(如果可用)(或斜体等)。

Objective-C中的主要代码是以下代码:

[attrString enumerateAttribute:NSFontAttributeName
                           inRange:NSMakeRange(0, [attrString length])
                           options:0
                        usingBlock:^(id value, NSRange range, BOOL *stop) {
                            UIFont *currentFont = (UIFont *)value; //Font currently applied in this range
                            if ([self isFont:currentFont sameAs:searchedFont]) //This is where it can be tricky
                            {
                            [attrString addAttribute:NSFontAttributeName
                                               value:replacementFont
                                               range:range];
                            }
    }];

根据您的需要可能的更改/适应:更改字体,但不更改大小:

[attrString addAttribute:NSFontAttributeName value:[UIFont fontWithName:replaceFontName size:currentFont.pointSize]; range:range];

测试代码示例:

UIFont *replacementFont = [UIFont boldSystemFontOfSize:12];
UIFont *searchedFont    = [UIFont fontWithName:@"Helvetica Neue" size:15];
UIFont *normalFont      = [UIFont italicSystemFontOfSize:14];

NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:@"Lorem ipsum dolor sit amet,"];

NSAttributedString *attrStr1 = [[NSAttributedString alloc] initWithString:@"consectetuer adipiscing elit." attributes:@{NSFontAttributeName:searchedFont, NSForegroundColorAttributeName:[UIColor redColor]}];

NSAttributedString *attrStr2 = [[NSAttributedString alloc] initWithString:@" Aenean commodo ligula eget dolor." attributes:@{NSFontAttributeName:normalFont}];

NSAttributedString *attrStr3 = [[NSAttributedString alloc] initWithString:@" Aenean massa." attributes:@{NSFontAttributeName:searchedFont}];

NSAttributedString *attrStr4 = [[NSAttributedString alloc] initWithString:@"Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim."];

[attrString appendAttributedString:attrStr1];
[attrString appendAttributedString:attrStr2];
[attrString appendAttributedString:attrStr3];
[attrString appendAttributedString:attrStr4];

NSLog(@"AttrString: %@", attrString);

[attrString enumerateAttribute:NSFontAttributeName
                       inRange:NSMakeRange(0, [attrString length])
                       options:0
                    usingBlock:^(id value, NSRange range, BOOL *stop) {
                        UIFont *currentFont = (UIFont *)value;
                        if ([self isFont:currentFont sameAs:searchedFont])
                        {
            [attrString addAttribute:NSFontAttributeName
                               value:replacementFont
                               range:rangeEffect];
                        }
}];

NSLog(@"AttrString Changed: %@", attrString);

使用@TigerCoding的解决方案,这里是可能的代码:

NSInteger location = 0;
while (location < [attrString length])
{
    NSRange rangeEffect;
    NSDictionary *attributes = [attrString attributesAtIndex:location effectiveRange:&rangeEffect];
    if (attributes[NSFontAttributeName])
    {
        UIFont *font = attributes[NSFontAttributeName];
        if ([self isFont:font sameAs:searchedFont])
        {
            [attrString addAttribute:NSFontAttributeName value:replacementFont range:rangeEffect];
        }
    }
    location+=rangeEffect.length;
}

附带说明:进行一些优化测试(但需要进行一些研究)。 我想举几个例子,如果您对两个连续的范围应用相同的attributeS,则NSAttributedString会将它们“附加”为一个,以防您可能害怕连续应用相同的效果。 所以问题是,如果您有@{NSFontAttributeName:font1, NSForegroundColorAttributeName:color1}的范围为0,3和@{NSFontAttributeName:font1, NSForegroundColorAttributeName:color2} @{NSFontAttributeName:font1, NSForegroundColorAttributeName:color1}的范围为3,5将会enumerateAttribute:inRange:options:usingBlock:返回您0.5的范围? 它会比枚举每个索引更快吗?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM