第一篇技术博客就从最近遇到的一个小问题着手吧,顺便也来复习一下NSAttributedString的基本用法。
NSAttributedString
NSAttributedString叫做富文本,是一种带有属性的字符串,通过它可以轻松的在一个字符串中表现出多种字体、字号、字体大小等各不相同的风格,还可以对段落进行格式化。
富文本分为不可变(NSAttributedString)和可变(NSMutableAttributedString)两种类型,两者的区别在于初始化完成后可变类型可以对其内部的值进行修改操作(即:覆盖,插入,删除字符串等操作), 而不可变类型则反之。
由于NSAttributedString类型方法比较局限,我们直接创建继承自它的NSMutableAttributedString类型对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| // 常规初始化方法有三个 NSString *str = @"The first Technology blog"; // 1.直接赋值(NSString类型) - (instancetype)initWithString:(NSString *)str; NSMutableAttributedString *mutableAttributeStr1 = [[NSMutableAttributedString alloc]initWithString:str];
// 2.赋值并添加文本属性 - (instancetype)initWithString:(NSString *)str attributes:(nullable NSDictionary<NSString *, id> *)attrs; NSDictionary *attributesDic = @{NSFontAttributeName : [UIFont systemFontOfSize:20],NSForegroundColorAttributeName : [UIColor blueColor]}; NSMutableAttributedString *mutableAttributeStr2 = [[NSMutableAttributedString alloc]initWithString:str attributes:attributesDic];
// 3.直接赋值(NSAttributedString类型) - (instancetype)initWithAttributedString:(NSAttributedString *)attrStr; NSMutableAttributedString *mutableAttributeStr3 = [[NSMutableAttributedString alloc]initWithAttributedString:mutableAttributeStr2];
|
第一种初始化时:不能直接设置文本属性
第二种初始化时:可以设置文本属性
第三种初始化时:直接获取mutableAttributeStr2的文本属性
介绍完初始化方法,再来看一看它都有哪些属性:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| // NSFontAttributeName 设置字体属性,默认值:字体:Helvetica(Neue) 字号:12 // NSForegroundColorAttributeNam 设置字体颜色,取值为 UIColor对象,默认值为黑色 // NSBackgroundColorAttributeName 设置字体所在区域背景颜色,取值为 UIColor对象,默认值为nil, 透明色 // NSLigatureAttributeName 设置连体属性,取值为NSNumber 对象(整数),0 表示没有连体字符,1 表示使用默认的连体字符 // NSKernAttributeName 设定字符间距,取值为 NSNumber 对象(整数),正值间距加宽,负值间距变窄 // NSStrikethroughStyleAttributeName 设置删除线,取值为 NSNumber 对象(整数) // NSStrikethroughColorAttributeName 设置删除线颜色,取值为 UIColor 对象,默认值为黑色 // NSUnderlineStyleAttributeName 设置下划线,取值为 NSNumber 对象(整数),枚举常量 NSUnderlineStyle中的值,与删除线类似 // NSUnderlineColorAttributeName 设置下划线颜色,取值为 UIColor 对象,默认值为黑色 // NSStrokeWidthAttributeName 设置笔画宽度,取值为 NSNumber 对象(整数),负值填充效果,正值中空效果 // NSStrokeColorAttributeName 填充部分颜色,不是字体颜色,取值为 UIColor 对象 // NSShadowAttributeName 设置阴影属性,取值为 NSShadow 对象 // NSTextEffectAttributeName 设置文本特殊效果,取值为 NSString 对象,目前只有图版印刷效果可用: // NSBaselineOffsetAttributeName 设置基线偏移值,取值为 NSNumber (float),正值上偏,负值下偏 // NSObliquenessAttributeName 设置字形倾斜度,取值为 NSNumber (float),正值右倾,负值左倾 // NSExpansionAttributeName 设置文本横向拉伸属性,取值为 NSNumber (float),正值横向拉伸文本,负值横向压缩文本 // NSWritingDirectionAttributeName 设置文字书写方向,从左向右书写或者从右向左书写 // NSVerticalGlyphFormAttributeName 设置文字排版方向,取值为 NSNumber 对象(整数),0 表示横排文本,1 表示竖排文本 // NSLinkAttributeName 设置链接属性,点击后调用浏览器打开指定URL地址 // NSAttachmentAttributeName 设置文本附件,取值为NSTextAttachment对象,常用于文字图片混排 // NSParagraphStyleAttributeName 设置文本段落排版格式,取值为 NSParagraphStyle 对象
|
因为NSAttributedString的属性以字典的形式存在的,所以上面的属性作为key对应后面的value类型 即:@{key : value}形式。
富文本属性可以在初始化时直接设置,也可以在其初始化完成之后设置或添加(注意:初始化之后进行属性操作必须是NSMutableAttributedString类型):
- (void)setAttributes:(nullable NSDictionary *)attrs range:(NSRange)range;
- (void)addAttribute:(NSString *)name value:(id)value range:(NSRange)range;
- (void)addAttributes:(NSDictionary *)attrs range:(NSRange)range;
看到这里发现既有set又有add开头的方法, 那么顺便说一下在iOS中以set和add开头的方法的规律:
- 一般以set开头的方法是赋值操作,会覆盖掉上一次的操作
- 一般以add开头的方法是添加操作,多次添加一般会累加
- 注意: 这里的set开头的方法不包括setter方法
以addAttribute:value:range:和addAttributes:range:为例:1 2 3
| [mutableAttributeStr1 addAttributes:@{NSFontAttributeName : [UIFont boldSystemFontOfSize:50]} range:NSMakeRange(0, mutableAttributeStr1.length)]; [mutableAttributeStr1 addAttribute:NSBackgroundColorAttributeName value:[UIColor redColor] range:NSMakeRange(0, mutableAttributeStr1.length)]; //富文本最后的样式为:50号字体 红色背景
|
再来试一下setAttributes:range:方法:
1 2 3 4 5
| [mutableAttributeStr1 addAttributes:@{NSFontAttributeName : [UIFont boldSystemFontOfSize:50]} range:NSMakeRange(0, mutableAttributeStr1.length)]; [mutableAttributeStr1 addAttribute:NSBackgroundColorAttributeName value:[UIColor redColor] range:NSMakeRange(0, mutableAttributeStr1.length)]; [mutableAttributeStr1 setAttributes:@{NSFontAttributeName : [UIFont boldSystemFontOfSize:10]} range:NSMakeRange(0, mutableAttributeStr1.length)]; // 富文本最后的样式为: 10号字体 而前面设置的红色背景并没有了 // 现在区别应该显而易见了^ ^
|
忽略上面对mutableAttributeStr1的设置,现在我们为mutableAttributeStr1重新添加文本属性:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| [mutableAttributeStr1 addAttributes:@{NSFontAttributeName : [UIFont boldSystemFontOfSize:50], NSBackgroundColorAttributeName : [UIColor yellowColor]} range:NSMakeRange(0, 3)]; [mutableAttributeStr1 addAttributes:@{NSFontAttributeName : [UIFont boldSystemFontOfSize:70], NSForegroundColorAttributeName : [UIColor redColor], NSStrikethroughStyleAttributeName : @1} range:NSMakeRange(4, 5)]; [mutableAttributeStr1 addAttributes:@{NSFontAttributeName : [UIFont boldSystemFontOfSize:40], NSUnderlineStyleAttributeName : @1, NSUnderlineColorAttributeName : [UIColor purpleColor], NSStrokeWidthAttributeName : @4} range:NSMakeRange(10, 11)]; [mutableAttributeStr1 addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:50] range:NSMakeRange(21, 5)]; [mutableAttributeStr1 addAttribute:NSObliquenessAttributeName value:@0.3 range:NSMakeRange(21, 5)]; NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc]init]; paragraphStyle.lineSpacing = 170.0; paragraphStyle.firstLineHeadIndent = 30.0; paragraphStyle.headIndent = 100.0; [mutableAttributeStr1 addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:NSMakeRange(0, mutableAttributeStr1.length)]; self.myLabel.attributedText = mutableAttributeStr1;
|
其它属性效果自行测试,运行效果如下:

如果字符串str是一串带有html标签的字符串,我们要使用它的另一个初始化方法
-(nullable instancetype)initWithData:(NSData )data options:(NSDictionary<NSString , id> )options documentAttributes:(NSDictionary<NSString , id> __nullable __nullable)dict error:(NSError **)error
1 2 3
| NSString * htmlText = @"<b>The</b> first <h3>technology</h3> blog"; NSMutableAttributedString * mutableAttributeStr = [[NSMutableAttributedString alloc] initWithData:[htmlText dataUsingEncoding:NSUnicodeStringEncoding] options:@{ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType} documentAttributes:nil error:nil]; self.myLabel.attributedText = mutableAttributeStr;
|
NSDocumentTypeDocumentAttribute属性值:NSHTMLTextDocumentType 就是专门用来显示htmltext样式的 这样标签效果就能生效了 而不会把标签显示出来了。
但是我又想在不影响html标签里样式的同时设置标签外的字体大小为17, 我们需要使用它的另一个枚举属性方法
-(void)enumerateAttribute:(NSString )attrName inRange:(NSRange)enumerationRange options:(NSAttributedStringEnumerationOptions)opts usingBlock:(void (^)(id __nullable value, NSRange range, BOOL stop))block NS_AVAILABLE(10_6, 4_0);
1 2 3 4 5 6 7 8 9
| NSRange range = (NSRange){0, mutableAttributeStr.length}; [mutableAttributeStr enumerateAttribute:NSFontAttributeName inRange:range options:NSAttributedStringEnumerationLongestEffectiveRangeNotRequired usingBlock:^(id _Nullable value, NSRange range, BOOL * _Nonnull stop) { UIFont* currentFont = value; UIFont *replacementFont = nil; if ([currentFont.fontName rangeOfString:@"bold" options:NSCaseInsensitiveSearch].location == NSNotFound) { replacementFont = [UIFont systemFontOfSize:17.0f]; [mutableAttributeStr addAttribute:NSFontAttributeName value:replacementFont range:range]; } }];
|
因为标签样式都有加粗效果,那么在它的fontName中都带有bold字符(打印fontName依次为:TimesNewRomanPS-BoldMT,TimesNewRomanPSMT,TimesNewRomanPS-BoldMT,TimesNewRomanPSMT), 所以我们过滤一下没有加粗的部分 并设置为17号字体, 最终标签外的first 和 blog 就变成17号字体啦!
