2015-07-21 38 views
0

我在UITextView中使用了属性文本。 该文本包含许多字体。Attributed文本,使用swift替换另一个特定的字体

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

任何快速的方法呢? :)

+0

您可以为要替换的字体取文本的范围,并在同一范围上应用要应用的新字体。 – sanjana

+0

感谢您的建议。手动做这件事是不可能的,因为我有很多rtf。所有需要替换字体的特定字体。 – Franck

+0

我的意思是代码不是手动:) – sanjana

回答

1

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

我使用的方法是enumerateAttribute:inRange:options:usingBlock:只能看到NSFontAttributeName

还有一点是没有讨论的:如何认识到字体是搜索的字体。您是否在寻找familyNamefontName(属性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将“附加到”一个,以防你可能害怕连续应用相同的效果。 所以,问题是,如果你有 @{NSFontAttributeName:font1, NSForegroundColorAttributeName:color1}的范围0,3 和 @{NSFontAttributeName:font1, NSForegroundColorAttributeName:color2}的范围3,5 威尔enumerateAttribute:inRange:options:usingBlock:回报,你的范围内0,5?它会比枚举每个索引更快吗?

1

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

您需要迭代每个索引以存储字体。它会很慢,因为在文本文件中,字体可能会改变每个字符。所以我会建议从主线程开始。

+0

嗨。 Ouch。希望有一个更快的方法。无论如何,看起来这是一种方式。:) – Franck

+0

我怀疑有一个更快的方法,因为你必须检查每个字符索引。希望这可以帮助。 – TigerCoding

+0

这是否解决了您的问题? – TigerCoding

相关问题