[英]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.