运用Text Kit包制作和办理文本
UIKit结构包括几个用于在运用程序的用户界面中显现文本的类:UITextView、UITextField和UILabel,如Displaying Text Content in iOS中所述。从UITextView类创立的Text views用于显现很多文本。底层UITextView是一个强壮的布局引擎,称为Text Kit。假如您需求自界说布局进程或需求干涉该行为,则能够运用Text Kit。关于数量较少的文本和需求定制解决方案的特殊需求,能够运用代替的、较低级别的技能,如Lower Level Text-Handling Technologies中所述。
Text Kit是UIKit结构中的一组类和协议,供给高质量的排版服务,使运用程序能够存储,布局和显现具有良好排版的一切特征的文本,例如字距离(kerning),连体字(ligatures),line breaking和对齐(justification)。Text Kit是建立在Core Text之上,所以它供给相同的速度和能力。UITextView与Text Kit彻底集成;它供给修正和显现功用,答应用户输入文本、指定格式化特点和查看成果。其他Text Kit类供给文本存储和布局功用。Text Kit在其他iOS文本和图形结构中的方位如图8-1所示。
Figure 8-1Text Kit Framework Position
Text Kit使您能够彻底操控用户界面元素中的文本出现。除了UITextView, UITextField和UILabel都是建立在Text Kit之上的,它与动画,UICollectionView和UITableView无缝集成。Text Kit选用彻底可扩展的面向目标体系结构设计,支撑子类化、托付和一组完整的告诉,然后实现深度定制。
Text Kit主要目标
主要Text Kit目标之间的数据流途径如图8-2所示。Text views是UITextView类的实例,Text containers是NSTextContainer类的实例,layout manager是NSLayoutManager类的实例,文本存储是NSTextStorage类的实例。在Text Kit中,NSTextStorage目标存储文本,这个文本是由UITextView目标显现,并由NSLayoutManager目标布局,由NSTextContainer目标界说的区域的文本。
Figure 8-2Primary Text Kit Objects
一个NSTextContainer目标界说了一个文本能够布局的区域。一般,文本容器界说了一个矩形区域,可是经过创立NSTextContainer的子类,您能够创立其他形状,例如圆形、五边形或不规则形状。文本容器不仅描绘了一个能够用文本填充的区域的概括,还保护了一个贝塞尔途径数组,这些途径是其区域内不进行文本布局的扫除区域。当进行布局时,文本会围绕这些扫除途径流动,供给了一种包括图形和其他非文本布局元素的办法。
译者注:扫除区域便是被贝塞尔曲线画出来不让文字布局的当地
NSTextStorage界说了Text Kit扩展文本处理体系的基本存储机制。NSTextStorage是NSMutableAttributedString的子类,用于存储文本体系操作的字符和特点。它保证文本和特点在修正操作中保持共同的状况。除了存储文本之外,NSTextStorage目标还办理一组客户端NSLayoutManager目标,告诉它们字符或特点的任何更改,以便它们能够依据需求传递和从头显现文本。
注意:只要运用程序能够保证从单个线程拜访,即便经过子线程,也能够拜访NSLayoutManager、NSTextStorage和NSTextContainer。(也便是你要一直经过一个线程拜访,子线程和主线程都行)
For reference information aboutUITextView
, seeUITextView Class Reference.NSTextContainer
is described inNSTextContainer Class Reference for iOS,NSLayoutManager
inNSLayoutManager Class Reference for iOS, andNSTextStorage
inNSTextStorage Class Reference for iOS.
文本特点(Text attributes)
Text Kit处理三种文本特点:字符特点(character)、阶段特点(paragraph)和文档特点(document)。字符特点包括字体、色彩和下标等特征,能够与单个字符或多个字符相相关。阶段特点包括缩进、制表符和行距离等特征。文档特点包括文档规模的特点,如纸张巨细、边距和视图缩放百分比。
字符特点(Character Attributes)
特点字符串将字符特点作为键值对存储在NSDictionary目标中。键是由特点称号表明的标识符(NSString常量),例如NSFontAttributeName。图8-3显现了将带有特点字典的attributed string运用到一个字符串的一段中。
Figure 8-3Composition of an attributed string
从概念上讲,特点字符串中的每个字符都有一个相关的特点字典。可是,一般一个特点字典适用于较长的字符区间,也便是一段文本。NSAttributedString类供给了在给定字符索引处回来相关的特点字典和特点值适用规模的办法,例如attributesAtIndex:effectiveRange:。
除了与预界说的特点一起作业外,您还能够为一段字符规模分配任何您挑选的特点键值对。您将特点增加到NSTextStorage目标中适当的字符规模,运用addAttribute:value:range:办法。您还能够创立一个包括自界说特点称号和值的NSDictionary目标,并运用addAttributes:range:办法将它们增加到字符规模中。要运用您的自界说特点,您需求一个自界说的NSLayoutManager子类来处理它们。您的子类应该重写drawGlyphsForGlyphRange:atPoint:办法。您的掩盖能够首要调用父类来制作字形规模,然后在上面制作自己的特点。或许,您的掩盖能够彻底按自己的办法制作字形。
阶段特点(Paragraph Attributes)
阶段特点影响布局办理器将文本行摆放成页面上的阶段的办法。文本体系将阶段特点封装在NSParagraphStyle类目标中。预界说字符特点之一NSParagraphStyleAttributeName的值指向一个NSParagraphStyle目标。特点固定保证每个阶段只涉及一个NSParagraphStyle目标。
阶段特点包括对齐、制表位、换行形式和行距离(也称为leading)等特征。
文档特点(Document Attributes)
文档特点与整个文档相相关。文档特点包括纸张巨细、边距和视图缩放百分比等特征。虽然文本体系没有内置机制来存储文档特点,可是NSAttributedString初始化办法(如initWithRTF:documentAttributes:)能够从RTF或HTML数据流派生文档特点,并将它们填充到您供给的NSDictionary目标中。相反,假如您传递包括它们的NSDictionary目标的引用,那么写入RTF数据的办法(如RTFFromRange:documentAttributes:)也会写入文档特点。(这儿看不懂去看下api的文档就理解了,苹果写的太拗口了)
特点固定(Attribute Fixing)
修正特点字符串或许会导致不共同性,有必要经过特点固定来清理这种不共同性。UIKit对NSMutableAttributedString的扩展界说了fixAttributesInRange:办法来修正附件、字符和阶段特点之间的共同性问题。这些办法保证在删除附件字符后不会保留附件,保证字符特点仅适用于可用的字体中的字符,并保证整个阶段中的阶段特点是共同的。
经过编程办法更改文本存储(Text Storage)
NSTextStorage是Text Kit结构中的一个类,用于存储字符数据。这些数据以特点字符串的形式存在,即包括Unicode编码的字符序列及其相关特点(如字体、色彩和阶段款式)。NSAttributedString和NSMutableAttributedString表明这些特点字符串,NSTextStorage是它们的子类。
在更改文本存储目标时,分为三个阶段:
- 首要,向其发送beginEditing音讯,宣告一组更改。
- 在第二阶段,发送一些修正音讯,如replaceCharactersInRange:withString:和setAttributes:range:,以更改字符或特点。每次发送此类音讯时,文本存储目标会调用edited:range:changeInLength:来盯梢自收到beginEditing音讯以来受影响的字符规模。
- 在第三阶段,当完成对文本存储目标的更改时,向其发送endEditing音讯。这会导致文本存储目标发送托付音讯textStorage:willProcessEditing:range:changeInLength:并调用其自己的processEditing办法,在记载的更改字符规模内修正特点。有关特点修正的信息,请参见Attribute Fixing。
在修正其特点后,文本存储目标会发送托付办法textStorage:didProcessEditing:range:changeInLength:,使托付有时机验证并或许更改特点。(尽管托付能够在此办法中更改文本存储目标的字符特点,但不能在文本存储处于不共同状况的情况下更改字符自身。)最终,文本存储目标向每个相关的布局办理器发送processEditingForTextStorage:edited:range:changeInLength:invalidatedRange:音讯,指示文本存储目标中已更改的规模以及这些更改的性质。布局办理器会运用此信息从头核算字形方位,并在必要时进行从头显现。
运用字体目标(Font Objects)进行作业。
核算机字体是一种数据文件,格式为OpenType或TrueType等,包括描绘一组字形的信息(如字符和字形中所述),以及用于字形渲染的各种弥补信息。UIFont类供给了获取和设置字体信息的接口。UIFont实例供给对字体特征和字形的拜访。Text Kit将字符信息与字体信息相结合,在文本布局期间挑选运用的字形。字体目标是不可变的,因此在您的运用程序中从多个线程运用它们是安全的。
您不会运用alloc和init办法来创立UIFont目标;相反,您运用preferredFontForTextStyle:或fontWithName:size:。您还能够运用字体描绘符来创立具有fontWithDescriptor:size:的字体。这些办法查看具有指定特征的现有字体目标,假如存在则回来它。不然,它们会查找所恳求的字体数据并创立相应的字体目标。
文本款式(Text Styles)
文本款式(在iOS 7中引进)是对字体预期用处的语义描绘,并经过称为动态类型(Dynamic Type)的机制实现。文本款式按用处组织,并由UIFontDescriptor.h中界说的常量表明,如表8-1所示。实践字体能够依据许多动态要素而改变,包括用户的内容巨细类别偏好,它由UIApplication特点preferredContentSizeCategory表明。要获取给定文本款式的字体目标,您能够将相应的常量传递给UIFont办法的preferredFontForTextStyle:。要获取文本款式的字体描绘符,请将常量传递给UIFontDescriptor办法的preferredFontDescriptorWithTextStyle:。(这儿的功用看下设置里边的动态字体体验一下就好了, 我手机是iOS 16体系,在体系设置-辅佐功用-显现于文字巨细-更大字体)
Table 8-1Text style constants
Constant | Usage |
---|---|
UIFontTextStyleHeadline |
The font used for headings. |
UIFontTextStyleSubheadline |
The font used for subheads. |
UIFontTextStyleBody |
The font used for body text. |
UIFontTextStyleFootnote |
The font used for footnotes. |
UIFontTextStyleCaption1 |
The font used for standard captions. |
UIFontTextStyleCaption2 |
The font used for alternate captions. |
文本款式经过动态类型机制为运用程序带来了许多优势,一切这些优势都增强了文本的可读性。动态类型以和谐的办法呼运用户偏好,并呼应辅佐功用设置,以进步可读性和超大字体。也便是说,当调用preferredFontForTextStyle:时,回来的特定Font包括依据用户首选项和上下文而改变的特征,包括盯梢(字母距离)调整,以及针对特定文本款式常量指定的调优。
运用文本款式常量回来的字体旨在用于运用程序中除用户界面元素(如按钮、栏和标签)中的文本之外的一切文本。天然,您需求挑选合适您运用程序的文本款式。调查UIContentSizeCategoryDidChangeNotification也很重要,这样当用户更改内容巨细类别时,您能够从头布局文本。当您的运用程序收到该告诉时,它应该向由Auto Layout布局的视图发送invalidateIntrinsicContentSize音讯,或向手动布局的用户界面元素发送setNeedsLayout。并且它应该使首选字体或字体描绘符无效,并依据需求获取新的字体或字体描绘符。
Using Font Descriptors
字体描绘符是从UIFontDescriptor类实例化的,供给了一种用特点字典描绘字体的办法,并用于创立UIFont目标。特别是,您能够从字体描绘符创立UIFont目标,从UIFont目标获取描绘符,更改描绘符并运用它创立新的字体目标。您还能够运用字体描绘符来指定运用程序供给的自界说字体。
字体描绘符能够进行归档,这是运用文本款式的一个优势。您不应该缓存由文本款式指定的字体目标,由于它们是动态的——它们的特征会随着时间的推移依据用户偏好而改变。但您能够缓存字体描绘符以保留字体的描绘,然后在稍后解压缩并运用它创立具有相同特征的字体目标。
您能够运用字体描绘符查询体系以获取与特定特点匹配的可用字体,然后创立与这些特点匹配的字体实例,例如称号、特征、语言和其他功用。例如,您能够运用字体描绘符检索与给定字体族名匹配的一切字体,运用CSS规范界说的族名,如清单8-1所示。
Listing 8-1Font family name matching
UIFontDescriptor *helveticaNeueFamily =
[UIFontDescriptor fontDescriptorWithFontAttributes:@{
UIFontDescriptorFamilyAttribute: @"Helvetica Neue"
}];
NSArray *matches =
[helveticaNeueFamily matchingFontDescriptorsWithMandatoryKeys: nil];
如图所示的matchingFontDescriptorsWithMandatoryKeys:办法回来一个数组,其间包括体系上一切Helvetica Neue字体的字体描绘符,如HelveticaNeue、HelveticaNeue-Medium、HelveticaNeue-Light、HelveticaNeue-Thin等。
您能够经过运用符号特征,如粗体、斜体、扩展和紧缩,来修正preferredFontForTextStyle:回来的字体。您能够运用字体描绘符来修正特定的特征,如清单8-2所示。
Listing 8-2 Font trait modification
UIFontDescriptor *fontDescriptor =
[UIFontDescriptor preferredFontDescriptorWithTextStyle: UIFontTextStyleBody];
UIFontDescriptor *boldFontDescriptor =
[fontDescriptor fontDescriptorWithSymbolicTraits: UIFontDescriptorTraitBold];
UIFont *boldFont = [UIFont fontWithDescriptor: boldFontDescriptor size: 0.0];
此代码片段首要检索正文文本款式的字体描绘符,然后修正该字体描绘符以指定粗体特征,最终运用UIFont类办法fontWithDescriptor:size:回来具有粗体特征的正文文本款式的实践字体目标。 经过fontWithDescriptor:size传递size值0.0:指定保留开始与Font描绘符一起回来的size特点。当然,这种行为是需求的,由于Font巨细是由动态类型机制决定的。
激活字体功用(Font Features)
字体描绘符的另一个重要用处是激活和挑选字体功用。字体功用是字体的排版特点,当字体的字形由文本体系出现时,它们操控其外观的各个方面。只要在字体设计者挑选包括它们时,字体功用才可用。一些字体功用在少数字体中可用,而另一些则在许多字体中常见。此外,安装在不同平台上的同一字体的不同版本或许在可用的字体功用方面有所不同。
字体功用被分成组后称为功用类型(feature types),在其间单个功用挑选器挑选特定的功用设置。功用类型能够是排他的或非排他的。假如功用类型是排他的,则一次只能挑选一个可用的功用挑选器,例如数字是等宽的还是固定宽度的。假如功用类型对错排他的,则能够同时启用恣意数量的功用挑选器。例如,关于连字功用类型,您能够挑选字体支撑的可用连字类的恣意组合。
注意:假如您挑选了字体中不可用的功用,您将不会看到字体字形外观的改变。
一些功用是上下文的,而另一些对错上下文的。上下文功用运用于字形的办法取决于字形与相邻字形的方位联系。文本体系布局功用的强壮之处在于它能够主动运用杂乱的上下文处理。
非上下文功用以相同的办法运用于字形,而不考虑相邻的字形。这些功用包括挑选备用字形集以赋予文本不同的外观,以及用于数学排版或增强排版杂乱性的字形替换。
例如,清单8-3中的代码激活了Helvetica Neue Medium字体界说的两个功用类型。
Listing 8-3 Activating Font Features
NSArray *timeFeatureSettings = @[
@{
UIFontFeatureTypeIdentifierKey: @(kNumberSpacingType),
UIFontFeatureSelectorIdentifierKey: @(kProportionalNumbersSelector)
},
@{
UIFontFeatureTypeIdentifierKey: @(kCharacterAlternativesType),
UIFontFeatureSelectorIdentifierKey: @(2)
}];
UIFont *originalFont = [NSFont fontWithName: @"HelveticaNeue-Medium" size: 12.0];
UIFontDescriptor *originalDescriptor = [originalFont fontDescriptor];
UIFontDescriptor *timeDescriptor = [originalDescriptor
fontDescriptorByAddingAttributes: @{
UIFontDescriptorFeatureSettingsAttribute: timeFeatureSettings }];
UIFont *timeFont = [UIFont fontWithDescriptor: timeDescriptor size: 12.0];
清单8-3中的代码激活了数字距离功用类型(由常量kNumberSpacingType表明),挑选了等宽数字(kProportionalNumbersSelector),并激活了字符代替功用类型(kCharacterAlternativesType),其特征挑选器标识符键值为2。本例中用于表明字体功用类型和挑选器的常量在Core Text结构的SFNTLayoutTypes.h头文件中声明为枚举(CoreText/CoreText.h)。字符代替类型的情况下,没有预界说的常量来表明特征挑选器标识符,因此您只需运用字体界说的数值。
由于字体功用由字体界说,确认支撑的功用的最可靠办法是直接查询字体。您能够运用Core Text中的CTFontCopyFeatures函数来履行此操作,如清单8-4所示。
Listing 8-4 Querying Font Features
UIFont *font = [UIFont fontWithName: @"HelveticaNeue-Medium" size: 12.0];
CFArrayRef fontFeatures = CTFontCopyFeatures((__bridge CTFontRef) font);
NSLog(@"properties = %@", fontFeatures);
清单8-5展现了由清单8-4中的CTFontCopyFeatures函数得到的字体特征数组,它显现在操控台日志中。
Listing 8-5 Typical Result from CTFontCopyFeatures Function
properties = (
{
CTFeatureTypeExclusive = 1;
CTFeatureTypeIdentifier = 6;
CTFeatureTypeName = "Number Spacing";
CTFeatureTypeNameID = 266;
CTFeatureTypeSelectors = (
{
CTFeatureSelectorDefault = 1;
CTFeatureSelectorIdentifier = 0;
CTFeatureSelectorName = "No Change";
CTFeatureSelectorNameID = 264;
},
{
CTFeatureSelectorIdentifier = 1;
CTFeatureSelectorName = "Proportional Numbers";
CTFeatureSelectorNameID = 267;
}
);
},
{
CTFeatureTypeExclusive = 1;
CTFeatureTypeIdentifier = 17;
CTFeatureTypeName = "Character Alternatives";
CTFeatureTypeNameID = 262;
CTFeatureTypeSelectors = (
{
CTFeatureSelectorDefault = 1;
CTFeatureSelectorIdentifier = 0;
CTFeatureSelectorName = "No Change";
CTFeatureSelectorNameID = 264;
},
{
CTFeatureSelectorIdentifier = 1;
CTFeatureSelectorName = "Alternate Punctuation";
CTFeatureSelectorNameID = 263;
},
{
CTFeatureSelectorIdentifier = 2;
CTFeatureSelectorName = "Numbers Punctuation";
CTFeatureSelectorNameID = 265;
}
);
}
)
在这种情况下,成果表明这个版本的Helvetica Neue Medium字体有两个字体功用:数字距离和字符代替。当您运用字体描绘符激活字体功用并挑选其设置时,此成果中最重要的值是功用类型标识符和功用挑选器标识符。您将这些值增加到表明字体功用设置的字典数组中,并将该数组作为UIFontDescriptorFeatureSettingsAttribute的值传递,依次传递给fontDescriptorByAddingAttributes:或fontDescriptorWithFontAttributes:办法,如清单8-3所示。该清单中显现的常量的枚举值与CTFontCopyFeatures函数回来的功用类型标识符和功用挑选器标识符的数值相相关。
如清单8-5所示,由CTFontCopyFeatures函数回来的字体特征数组还显现了功用类型是否是排他的,以及哪个功用挑选器是默认的。当然,功用类型称号和功用挑选器称号值供给了对可用字体功用及其设置的人类可读标识。
查询字体衡量
当字体衡量信息可用时,UIFont界说了许多办法用于拜访字体的衡量信息。比如ascender、capHeight、xHeight等特点都与规范的字体衡量信息相对应。图8-4显现了字体衡量怎么运用于字形尺度,表8-2列出了与各种衡量相关的特点称号。请参阅特点描绘以获取更详细的信息。
Figure 8-4Font metrics
Table 8-2Font metrics and relatedUIFont
methods
Font metric | Properties |
---|---|
X-height | xHeight |
Ascent | ascender |
Cap height | capHeight |
Line height | lineHeight |
Descent | descender |
Point size | pointSize |
文本布局
由NSLayoutManager类实例化的布局办理器目标是Text Kit中文本显现的中心操控目标。布局办理器履行以下操作:
- 操控文本存储和文本容器目标(Controls text storage and text container objects)
- 从字符生成字形(Generates glyphs from characters)
- 核算字形方位并存储信息(Computes glyph locations and stores the information)
- 办理字形和字符的规模 (Manages ranges of glyphs and characters)
- 在视图恳求时在文本视图中制作字形 (Draws glyphs in text views when requested by the view)
- 核算文本行的鸿沟框矩形 (Computes bounding box rectangles for lines of text)
- 操控连字符 (Controls hyphenation)
- 操作字符特点和字形特点 (Manipulates character attributes and glyph properties)t
在模型-视图-操控器范式中,布局办理器是操控器。NSTextStorage是NSMutableAttributedString的子类,它供给了模型的一部分,保存带有字体、款式、色彩和巨细等特点的字符字符串。NSTextContainer也能够被认为是模型的一部分,由于它模拟了文本布局的页面几何布局。UITextView(或其他UIView目标)供给了显现文本的视图。NSLayoutManager作为文本体系的操控器,由于它将文本存储目标中的字符转换为字形,依据一个或多个文本容器目标的尺度将它们摆放成行,并和谐一个或多个文本视图目标中的文本显现。
布局进程
布局办理器履行文本布局分为两个独立的进程:字形生成和字形布局。布局办理器以懒散的办法履行这两个布局进程,即在需求的基础上进行。因此,一些NSLayoutManager办法会导致字形生成,而另一些办法则不会,字形布局也是如此。在生成字形并核算其布局方位后,布局办理器会缓存这些信息以进步后续调用的性能。
布局办理器缓存字形、特点和布局信息。它盯梢由于文本存储中字符的更改而被无效化的字形规模。有两种办法能够使字符规模主动无效:假如需求生成字形或许需求摆放字形。假如您乐意,能够手动使字形或布局信息无效。当布局办理器收到需求了解无效规模内的字形或布局的音讯时,它会生成字形或从头核算布局。
生成行片段矩形
布局办理器将文本放置在NSTextContainer目标中的字形行内。这些行在文本容器内的布局由其形状和包括的任何扫除途径确认。无论行片段矩形在哪里与由扫除途径界说的区域相交,这些部分的行都有必要缩短或分段;假如整个区域有一个缺口,有必要移动与之堆叠的行以进行补偿。
布局办理器为给定的行主张一个矩形,然后要求文本容器调整矩形以适应它。主张的矩形一般跨过文本容器的鸿沟矩形,但它能够更窄或更宽,也能够部分或彻底位于鸿沟矩形之外。布局办理器向文本容器发送的音讯是lineFragmentRectForProposedRect:atIndex:writingDirection:remainingRect:,它会依据文本布局的方向,回来矩形中可用的最大矩形。它还回来一个包括一切剩余空间的矩形,例如文本容器中空泛或间隙的另一侧的剩余空间。
在进行文本布局时,布局办理器会进行最终一次调整。这个调整是由文本容器固定的一小部分,称为行片段填充,它界说了行片段矩形两头留白的部分。文本在行片段矩形内的方位会依据这个值进行调整(矩形自身不受影响)。填充答应对文本容器边缘(以及任何空泛周围)的区域进行小规模的调整,并使文本不会直接与其他在该区域邻近显现的图形相邻。您能够运用lineFragmentPadding特点更改填充的默认值。请注意,行片段填充不合适用于表达边距。关于文档边距,您应该设置UITextView目标在其包括视图中的方位和巨细。关于文本边距,您应该设置文本视图的textContainerInset特点。此外,您能够运用NSMutableParagraphStyle的特点(如headIndent)设置单个阶段的缩进值。
除了回来行片段矩形自身,布局办理器还回来一个称为已运用矩形的矩形。这是行片段矩形中实践包括字形或其他要制作的标记的部分。按照常规,两个矩形都包括行片段填充和行距离(依据字体的行高衡量和阶段的行距离参数核算)。可是,阶段距离(前后)和文本周围增加的任何空间(例如由居中空格文本引起的空间)只包括在行片段矩形中,而不包括在已运用矩形中。
指定扫除途径
文本容器保护一个表明接收器鸿沟矩形内扫除途径的UIBezierPath目标数组。当布局办理器向文本容器发送lineFragmentRectForProposedRect:atIndex:writingDirection:remainingRect:音讯,提议一个与扫除途径界说的区域相交的行片段矩形时,文本容器回来一个调整后的行片段矩形,扫除该区域。此进程如图8-6所示。
Figure 8-5Line fragment fitting
指定多页和多列布局
在最简略的情况下,Text Kit目标是按单个装备的,即一个文本存储目标、一个文本容器和一个布局办理器,如图8-6所示。当您在Interface Builder中从目标库拖动一个文本视图时,会主动实例化此装备。UITextView目标供给其他目标并将它们衔接在一起。您也能够在代码中创立此组织,如清单8-6所示。
Figure 8-6Object configuration for a single text flow
您也能够在代码中创立此组织,如清单8-6所示。这段代码能够在一个视图操控器中,例如,一个名为UIViewController的子类中,该子类有一个名为textContainer的NSTextContainer特点。
Listing 8-6 Object creation for a single text flow
NSTextStorage* textStorage = [[NSTextStorage alloc] initWithString:string];
NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
[textStorage addLayoutManager:layoutManager];
self.textContainer = [[NSTextContainer alloc] initWithSize:self.view.bounds.size];
[layoutManager addTextContainer:self.textContainer];
UITextView* textView = [[UITextView alloc] initWithFrame:self.view.bounds textContainer:self.textContainer];
[self.view addSubview:textView];
此装备仅限于只要一个文本容器和一个文本视图。在这样的组织中,文本在文本容器界说的区域内不间断地流动。此组织无法容纳分页符、多列布局和更杂乱的布局。
经过运用多个文本容器,每个都有一个相关的文本视图,能够实现更杂乱的布局组织。例如,为了支撑分页符,运用程序能够如图8-7所示装备文本目标。
Figure 8-7Object configuration for paginated text
现在有两个文本容器,而不是一个文本容器对应一个页面,每个文本容器操控文档的一部分。当文本被显现时,字形首要被放置在左上角的容器中。当该视图没有更多空间时,布局办理器会告诉其署理它已经填满了容器。署理能够查看是否有更多的文本需求布局,并在必要时增加另一个文本容器。布局办理器持续在下一个容器中布局文本,在完成后告诉署理,依此类推。同样,自界说视图(描绘为蓝色矩形)为这些文本列供给了画布。
您不仅能够拥有多个文本容器,还能够让多个NSLayoutManager目标拜访相同的文本存储。图8-9说明了具有多个布局办理器的目标摆放。这种组织的效果是供给同一文本的多个视图。假如用户在顶部视图中更改了文本,更改将立即反映在底部视图中(假设更改的方位在底部视图的鸿沟内)。
Figure 8-9Object configuration for multiple views of the same text
推荐阅读: 初识 TextKit