An NSAttributedString object manages character strings and associated sets of attributes (for example, font and kerning) that apply to individual characters or ranges of characters in the string.

这句话就是对这个类的一个最简明扼要的概括。NSAttributedString管理一个字符串,以及与该字符串中的单个字符或某些范围的字符串相关的属性。比如这个字符串“我北京天安门”,“我”跟其他字符的颜色不一样,而“北京”与其他的字体和大小不一样,等等。NSAttributedString就是用来存储这些信息的,具体实现时,NSAttributedString维护了一个NSString,用来保存最原始的字符串,另有一个NSDictionary用来保存各个子串/字符的属性。

Create Attributed String

有3种方法创建Attributed String。

1. 使用initWithString:, initWithString:attributes:, 或者 initWithAttributedString: ,下面是一个实例代码:

NSFont *font = [NSFont fontWithName:@"Palatino-Roman" size:14.0];
NSDictionary *attrsDictionary = [NSDictionary dictionaryWithObject:font
forKey:NSFontAttributeName];
NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:@"strigil"
attributes:attrsDictionary];

可以看到上面创建的整个字符串关联了Font属性。如果希望只是对某一范围的字符串施加某个属性应该使用NSMutableAttributedString的 setAttributes:range:方法。这里例子是使用了Font属性,在Appkit中特殊定义了若干属性,这些属性被用于Core Text中。其他的属性包括前景色、背景色、是否有shadow等,具体可见本文

2. 使用initWithRTF:documentAttributes:, initWithRTFD:documentAttributes:, and initWithRTFDFileWrapper:documentAttributes:从rich text (RTF) 或者 rich text with attachments (RTFD) 数据中创建。

NSData *rtfData = ...;  // assume rtfData is an NSData object containing valid RTF data
NSDictionary *docAttributes;
NSSize paperSize; NSAttributedString *attrString; if ((attrString = [[NSAttributedString alloc]
initWithRTF: rtfData documentAttributes: &docAttributes])) { NSValue *value = [docAttrs objectForKey:@"PaperSize"];
paperSize = [value sizeValue];
// implementation continues...

3. 使用initWithHTML:documentAttributes: 和 initWithHTML:baseURL:documentAttributes:从HTML数据中创建。有线程安全问题,使用时需要注意。

对RTF和HTML的支持都是AppKit对NSAttributedString的扩展。

Accessing Attributes

从上面对这个类的介绍可以知道,如果我们要访问某个子串/字符的属性,需要提供子串的位置和属性的名字,而如果不提供属性名字,那就把所有属性都返回。下面就是其对应的APIs:

attributesAtIndex:effectiveRange:
attributesAtIndex:longestEffectiveRange:inRange:
attribute:atIndex:effectiveRange:
attribute:atIndex:longestEffectiveRange:inRange:
fontAttributesInRange:
rulerAttributesInRange:

fontAttributesInRange: 和 rulerAttributesInRange: 是由AppKit扩展的属性。

The first four methods also return by reference the effective range and the longest effective range of the attributes. These ranges allow you to determine the extent of attributes. Conceptually, each character in an attributed string has its own collection of attributes; however, it’s often useful to know when the attributes and values are the same over a series of characters. This allows a routine to progress through an attributed string in chunks larger than a single character. In retrieving the effective range, an attributed string simply looks up information in its attribute mapping, essentially the dictionary of attributes that apply at the index requested. In retrieving the longest effective range, the attributed string continues checking characters past this basic range as long as the attribute values are the same. This extra comparison increases the execution time for these methods but guarantees a precise maximal range for the attributes requested.

Methods that return an effective range by reference are not guaranteed to return the maximal range to which the attribute(s) apply; they are merely guaranteed to return some range over which they apply. In practice they will return whatever range is readily available from the attributed string's internal storage mechanisms, which may depend on the implementation and on the precise history of modifications to the attributed string.

那些用reference返回有效范围的方法并不保证一定返回attribute应用的最大范围。它们只保证返回那些attribute有效的一些范围。实际上,它们只是返回attributed string中容易返回的那些信息,是否容易与内部实现,已经对attributed string的精确修改历史有关。

Methods that return a longest effective range by reference, on the other hand, are guaranteed to return the longest range containing the specified index to which the attribute(s) in question apply (constrained by the value of the argument passed in forinRange:). For efficiency, it is important that the inRange: argument should be as small as appropriate for the range of interest to the client.

那些返回最长有效范围的方法时能够保证返回制定attribute有效的最长的range的。为了效率,inRange: 参数应该尽量小,能满足客户需要就好。

When you iterate over an attributed string by attribute ranges, either sort of method may be appropriate depending on the situation. If there is some processing to be done for each range, and you know that the full range for a given attribute is going to have to be handled eventually, it may be more efficient to use the longest-effective-range variant, so as not to have to handle the range in pieces. However, you should use the longest-effective-range methods with caution, because the longest effective range could be quite long—potentially the entire length of the document, if the inRange: argument is not constrained.

Changing an Attributed String

NSMutableAttributedString提供若干方法,即可以修改字符串,又可以修改字符串的属性。经过多次修改后,有些信息可能变的不一致了,为了让信息保持一致,可以使用下面的方法:

fixAttributesInRange:
fixAttachmentAttributeInRange:
fixFontAttributeInRange:
fixParagraphStyleAttributeInRange:
beginEditing
endEditing

这些方法都是AppKit的扩展功能。

Reference:

1. https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/AttributedStrings/AttributedStrings.html#//apple_ref/doc/uid/10000036-BBCCGDBG

2. https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ApplicationKit/Classes/NSAttributedString_AppKitAdditions/Reference/Reference.html#//apple_ref/doc/uid/20000167-BAJJCCFC

理解NSAttributedString的更多相关文章

  1. [BS-18] 对OC中不可变类的理解

    对OC中不可变类的理解 OC中存在很多不可变的类(如NSString,NSAttributedString,NSArray,NSDictionary,NSSet等),用它们创建的对象存在于堆内存中,但 ...

  2. 字符串属性 NSMutableAttributedString/NSAttributedString

    因为iOS7新出的NSTextStorge是NSMutableAttributedString的子类.所以要用好NSTextStorage.首先要学好NSMutableAttributedString ...

  3. NSAttributedString能否设置文字下划线?是否支持line break?

    #import <CoreText/CoreText.h> #import "ViewController.h" @interface ViewController ( ...

  4. 理解CSS视觉格式化

    前面的话   CSS视觉格式化这个词可能比较陌生,但说起盒模型可能就恍然大悟了.实际上,盒模型只是CSS视觉格式化的一部分.视觉格式化分为块级和行内两种处理方式.理解视觉格式化,可以确定得到的效果是应 ...

  5. 彻底理解AC多模式匹配算法

    (本文尤其适合遍览网上的讲解而仍百思不得姐的同学) 一.原理 AC自动机首先将模式组记录为Trie字典树的形式,以节点表示不同状态,边上标以字母表中的字符,表示状态的转移.根节点状态记为0状态,表示起 ...

  6. 理解加密算法(三)——创建CA机构,签发证书并开始TLS通信

    接理解加密算法(一)--加密算法分类.理解加密算法(二)--TLS/SSL 1 不安全的TCP通信 普通的TCP通信数据是明文传输的,所以存在数据泄露和被篡改的风险,我们可以写一段测试代码试验一下. ...

  7. node.js学习(三)简单的node程序&&模块简单使用&&commonJS规范&&深入理解模块原理

    一.一个简单的node程序 1.新建一个txt文件 2.修改后缀 修改之后会弹出这个,点击"是" 3.运行test.js 源文件 使用node.js运行之后的. 如果该路径下没有该 ...

  8. 如何一步一步用DDD设计一个电商网站(一)—— 先理解核心概念

    一.前言     DDD(领域驱动设计)的一些介绍网上资料很多,这里就不继续描述了.自己使用领域驱动设计摸滚打爬也有2年多的时间,出于对知识的总结和分享,也是对自我理解的一个公开检验,介于博客园这个平 ...

  9. 学习AOP之透过Spring的Ioc理解Advisor

    花了几天时间来学习Spring,突然明白一个问题,就是看书不能让人理解Spring,一方面要结合使用场景,另一方面要阅读源代码,这种方式理解起来事半功倍.那看书有什么用呢?主要还是扩展视野,毕竟书是别 ...

随机推荐

  1. 无法找到脚本*.VBS的脚本引擎解决办法

    当你在运行一些基于VBS脚本语言的文件时,系统可能报错.这时候可能是你的VBS脚本服务在注册表中出错了,原因可能是卸载或安装一些代码不规范的程序引起的.这里给出无法找到脚本引擎"vbscri ...

  2. SyncServer obj

  3. Unity5.3官方VR教程重磅登场-系列2

    作者:王寒链接:https://zhuanlan.zhihu.com/p/20485529来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 欢迎继续我们的学习. 北京时间 ...

  4. Working with Data » 使用Visual Studio开发ASP.NET Core MVC and Entity Framework Core初学者教程

    原文地址:https://docs.asp.net/en/latest/data/ef-mvc/intro.html The Contoso University sample web applica ...

  5. flasCC技术点记录

    [待测试特性] 一.C接口导出相关 1.重载函数. 2.虚函数. 3.template相关 二.内存相关 1.as直接往c分配的内存写数据. 2.c直接往as对象写数据. 三.C访问AS 1.访问as ...

  6. android动画小析

    这里所讲的动画,是android framework提供的动画框架里面的动画. 是view层级的动画.不涉及到底层opengl es相关的动画实现. 动画: 主要包括 Interpolation du ...

  7. 复杂TableView在iOS上的性能优化

    声明:本文翻译自<iOS performance optimization>,原文作者 Khang Vo.翻译本文纯属为了技术交流的目的,并不具有任何的商业性质,也不得利用本文内容进行商业 ...

  8. English substitute

    英语写作中替换掉用到发腻的↓常用词↓,吐血整理2小时~~   动词替换:   1.Improve 提高:   Promote: 促进AC之间的贸易 promote the trade between ...

  9. Js作用域链及变量作用域

    要理解变量的作用域范围就得先理解作用域链 用var关键字声明一个变量时,就是为该变量所在的对象添加了一个属性. 作用域链:由于js的变量都是对象的属性,而该对象可能又是其它对象的属性,而所有的对象都是 ...

  10. Search for a Range [LeetCode]

    Given a sorted array of integers, find the starting and ending position of a given target value. You ...