归属文本,使用swift替换另一个特定的字体 [英] Attributed text, replace a specific font by another using swift

查看:229
本文介绍了归属文本,使用swift替换另一个特定的字体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在UITextView中使用属性文本。
文本包含许多字体。

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



任何快速的方法呢? :)解决方案

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

我使用的方法是 enumerateAttribute:inRange:options:usingBlock: 只能查找 NSFontAttributeName



还有一点不是讨论:如何认识到字体是一个搜查的字体。您是否在寻找 familyName fontName 的属性> UIFont ?即使在同一个家族中,字体可能看起来有很大的不同,你可能想要搜索真正匹配相同名字的字体。
我已经讨论了一次关于字体名称

Objective-C中的主要代码是这样的:

$ $ p $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ b options:0
usingBlock:^(id value,NSRange range,BOOL * stop){
UIFont * currentFont =(UIFont *)value; //当前在这个范围内应用的字体
if([self isFont:currentFont sameAs:SearchesFont])//这就是它可能非常棘手的地方
{
[attrString addAttribute:NSFontAttributeName
值:replacementFont
范围:range];
}
}];

根据您的需要可能更改/改编:
更改字体,但不是大小:



$ $ p $ [attrString addAttribute:NSFontAttributeName value:[UIFont fontWithName:replaceFontName size:currentFont.pointSize];范围:范围];

示例测试代码:

  UIFont * replacementFont = [UIFont boldSystemFontOfSize:12]; 
UIFont * searchingFont = [UIFont fontWithName:@Helvetica Neuesize:15];
UIFont * normalFont = [UIFont italicSystemFontOfSize:14];

NSMutableAttributedString * attrString = [[NSMutableAttributedString alloc] initWithString:@Lorem ipsum dolor sit amet];

NSAttributedString * attrStr1 = [[NSAttributedString alloc] initWithString:@consectetuer adipiscing elit。属性:@ {NSFontAttributeName:SearchesFont,NSForegroundColorAttributeName:[UIColor redColor]}];

NSAttributedString * attrStr2 = [[NSAttributedString alloc] initWithString:@Aenean commodo ligula eget dolor。属性:@ {NSFontAttributeName:normalFont}];

NSAttributedString * attrStr3 = [[NSAttributedString alloc] initWithString:@Aenean massa。属性:@ {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:searchingFont])
{
[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:searchingFont])
{
[attrString addAttribute:NSFontAttributeName value:replacementFont range:rangeEffect];
}
}
location + = rangeEffect.length;

$ / code $ / $ p


一些优化测试(但将需要一些研究)。
我想从几个例子来看,如果你对两个连续的范围应用相同的属性, NSAttributedString 将会附加到,以防万一你害怕连续应用相同的效果。
所以问题是,如果你有
code> @ {NSFontAttributeName:font1,NSForegroundColorAttributeName:color1}
范围0,3

@ {NSFontAttributeName:font1,NSForegroundColorAttributeName:color2} 范围3,5
enumerateAttribute:inRange:options:usingBlock: 返回范围0,5?它会比枚举每个索引更快?


I'm using attributed text in a UITextView. The text contain many fonts.

I'm looking for a way to replace a particular font by another one.

Any swift approach for this? :)

解决方案

My code will be in Objective-C, but since we use both CocoaTouch, it should be the same logic.

The method I use is enumerateAttribute:inRange:options:usingBlock: to look only for NSFontAttributeName.

There is another point that isn't discussed: How recognize that the font is the one searched. Are you looking for familyName, fontName (property of UIFont? Even in the same family, font may look a lot different and you may want to search really for the one exactly matching the same name. I've discussed once about Font Names here. You may found it interesting in your case. Note that there are methods (that I didn't know at the time) that can get the Bold Name of the font if available (or italic, etc.)

The main code in Objective-C is this one:

[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];
                            }
    }];

Possible change/adaptation according to your needs: Change the font, but not the size:

[attrString addAttribute:NSFontAttributeName value:[UIFont fontWithName:replaceFontName size:currentFont.pointSize]; range:range];

Sample test code:

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);

With the solution of @TigerCoding, here is the possible code:

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;
}

As a side note: A few optimization to test (but will need some research). I think from a few example that if you apply the same attributeS for two consecutive range, NSAttributedString will "appends them" into one, in case you may be afraid to apply the same effect consecutively. So the question is that if you have @{NSFontAttributeName:font1, NSForegroundColorAttributeName:color1} for range 0,3 and @{NSFontAttributeName:font1, NSForegroundColorAttributeName:color2} for range 3,5 Will enumerateAttribute:inRange:options:usingBlock: return you the range 0,5? Will it be faster than enumerating each indexes?

这篇关于归属文本,使用swift替换另一个特定的字体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆