[英]Attributed text, replace a specific font by another using swift
我在UITextView中使用属性文本。 文本包含许多字体。
我正在寻找一种将另一种字体替换为另一种字体的方法。
有什么快速的方法吗? :)
有一个称为attributesAtIndex(_:effectiveRange:)
。 此方法返回一个字典,您可以从中获取字体。
您将需要遍历每个索引来存储字体。 这会很慢,因为在文本文件中,字体可能会更改每个字符。 因此,我建议在主线程之外执行此操作。
我的代码将在Objective-C中进行,但是由于我们同时使用了CocoaTouch,因此逻辑应该相同。
我使用的方法是enumerateAttribute:inRange:options:usingBlock:
仅查找NSFontAttributeName
。
还有一点没有讨论:如何识别字体是搜索到的字体。 您是否要查找familyName
, fontName
( UIFont
属性?即使在同一个家族中,字体看起来也可能有很大不同,并且您可能想真正地搜索完全匹配相同名称的字体。我在这里曾经讨论过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.