我在UITextView中使用了属性文本。 该文本包含许多字体。
我正在寻找另一种替换特定字体的方法。
任何快速的方法吗? :)
答案 0 :(得分:1)
有一种名为attributesAtIndex(_:effectiveRange:)
的方法。此方法返回一个字典,您可以从中获取字体。
您需要遍历每个索引以存储字体。它会很慢,因为在文本文件中,字体可能会改变每个字符。因此我建议在主线程中执行此操作。
答案 1 :(得分:1)
我的代码将在Objective-C中,但由于我们同时使用CocoaTouch,它应该是相同的逻辑。
我使用的方法是enumerateAttribute:inRange:options:usingBlock:
,仅查看NSFontAttributeName
。
还有另一点没有讨论:如何识别字体是搜索到的字体。您是否正在寻找familyName
,fontName
(UIFont
的属性?即使在同一个系列中,字体也可能看起来很不一样,您可能希望真正搜索与其完全匹配的字体名称。
我已经讨论过一次字体名称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的范围?它会比枚举每个索引更快吗?