归因于文本,使用swift替换另一个特定字体

时间:2015-07-21 18:25:33

标签: swift fonts uitextview nsattributedstring

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

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

任何快速的方法吗? :)

2 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:1)

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

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

还有另一点没有讨论:如何识别字体是搜索到的字体。您是否正在寻找familyNamefontNameUIFont的属性?即使在同一个系列中,字体也可能看起来很不一样,您可能希望真正搜索与其完全匹配的字体名称。 我已经讨论过一次字体名称here。你可能会发现它很有趣。请注意,有些方法(我当时并不知道)可以获得字体的粗体名称(如果可用)(或斜体等)

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;
}

作为旁注: 一些优化测试(但需要一些研究)。 我想从一些例子来看,如果你为两个连续的范围应用相同的属性,NSAttributedString将&#34;追加它们&#34;如果您可能害怕连续应用相同的效果。 所以问题是,如果你有 范围0,3 @{NSFontAttributeName:font1, NSForegroundColorAttributeName:color1}@{NSFontAttributeName:font1, NSForegroundColorAttributeName:color2}范围为3,5 将enumerateAttribute:inRange:options:usingBlock:返回0,5的范围?它会比枚举每个索引更快吗?