属性文本,使用 swift 将特定字体替换为另一种
Attributed text, replace a specific font by another using swift
我在 UITextView 中使用属性文本。
文字包含多种字体。
我正在寻找一种将特定字体替换为另一种字体的方法。
对此有什么swift方法吗? :)
有一种方法叫做attributesAtIndex(_:effectiveRange:)
。此方法 returns 您可以从中获取字体的字典。
您需要遍历每个索引来存储字体。它会很慢,因为在文本文件中,字体可能会改变每个字符。所以我建议在主线程之外执行此操作。
我的代码会在Objective-C里,但是既然我们都用了CocoaTouch,应该是一样的逻辑。
我用的方法是enumerateAttribute:inRange:options:usingBlock:
只找NSFontAttributeName
.
还有一点没有讨论:如何识别字体是搜索到的字体。您是否在寻找 familyName
、fontName
(属性 of 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];
}
}];
可能change/adaptation根据您的需要:
更改字体,但不更改大小:
[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
将 "appends them" 合并为一个,以防你可能害怕连续应用相同的效果。
所以问题是如果你有
@{NSFontAttributeName:font1, NSForegroundColorAttributeName:color1}
范围 0,3
和
@{NSFontAttributeName:font1, NSForegroundColorAttributeName:color2}
范围 3,5
请问enumerateAttribute:inRange:options:usingBlock:
return 你的范围是0,5?它会比枚举每个索引更快吗?
我在 UITextView 中使用属性文本。 文字包含多种字体。
我正在寻找一种将特定字体替换为另一种字体的方法。
对此有什么swift方法吗? :)
有一种方法叫做attributesAtIndex(_:effectiveRange:)
。此方法 returns 您可以从中获取字体的字典。
您需要遍历每个索引来存储字体。它会很慢,因为在文本文件中,字体可能会改变每个字符。所以我建议在主线程之外执行此操作。
我的代码会在Objective-C里,但是既然我们都用了CocoaTouch,应该是一样的逻辑。
我用的方法是enumerateAttribute:inRange:options:usingBlock:
只找NSFontAttributeName
.
还有一点没有讨论:如何识别字体是搜索到的字体。您是否在寻找 familyName
、fontName
(属性 of 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];
}
}];
可能change/adaptation根据您的需要: 更改字体,但不更改大小:
[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
将 "appends them" 合并为一个,以防你可能害怕连续应用相同的效果。
所以问题是如果你有
@{NSFontAttributeName:font1, NSForegroundColorAttributeName:color1}
范围 0,3
和
@{NSFontAttributeName:font1, NSForegroundColorAttributeName:color2}
范围 3,5
请问enumerateAttribute:inRange:options:usingBlock:
return 你的范围是0,5?它会比枚举每个索引更快吗?