Text Kitによるテキストレイアウト(前編)

2014年10月15日(水)
西方 夏子(にしかた・なつこ)
UIKit徹底解説 iOSユーザーインターフェイスの開発
iPhone/iPadアプリのUI開発テクニックを完全網羅!Amazon詳細ページへ

この記事は、書籍『UIKit徹底解説 iOSユーザーインターフェイスの開発』の内容を、Think IT向けに特別公開しているものです。

これまでに解説した内容は、フォントまたはテキストレベルでのアピアランス設定方法です。さらに高いレベルでテキストコンテンツのアピアランスを調整するには、Text Kitのメイン機能であるNSTextContainer(テキストコンテナ)、NSLayoutManager(レイアウトマネージャ)、そしてNSTextStorage(テキストストレージ)を利用します。

Text Kitの構造

Text Kitとは、UIKitの一部として構築されているテキスト表現のためのフレームワークを指します。Text KitはCore Text上に位置し、Core Textが持つ機能をUIKit内で簡単に利用できる構造となっています。
Text Kitが導入されたiOS 7では、UILabelやUITextField、UITextViewが、Text Kitを使用するように再構築されています。そのため、本章で既に解説してきた内容も実際には、Text Kitの一部を利用していることになります。

Text Kitの主機能は、NSTextContainer、NSLayoutManager、NSTextStorageという3つのクラスを利用したUITextViewへのテキスト表示です。
まず、これらの3クラスの役割を説明します。

NSTextContainer(テキストコンテナ)

NSTextContainerは、UITextView上に表示するテキストの座標と形状を定義します。
1つのUITextViewは、1つのテキストコンテナを持ちます。テキストコンテナは1ページを表現しているともいえるので、1ページに入らない長いテキストコンテンツは、複数のテキストコンテナに分割して管理することができます。
また、exclusionPathsを設定することで、テキストの非表示領域も指定できます。テキストの非表示領域に画像を貼り付ければ、いわゆるテキストの回り込み処理が可能です。

NSLayoutManager(レイアウトマネージャ)

NSLayoutManagerは、UITextView上にテキスト表示する際に、レイアウトとレンダリングに関する調整を行います。テキストを表示すべき座標と形状はテキストコンテナから、実際に表示するテキストコンテンツは、次に説明するテキストストレージから受け取ります。
1つのレイアウトマネージャは、1つまたは複数のテキストコンテナを持ち、1つのテキストストレージを持ちます。レイアウトマネージャが持つテキストコンテナの数は、テキストコンテンツの長さに依存します。テキストストレージが持つ全コンテンツを収容できるだけのテキストコンテナを管理する必要があります。
また、レイアウトに関する様々な情報を持っています。例えば、UITextView上の特定の座標に表示されている文字またはグリフのインデックスを取得することもできます。

NSTextStorage(テキストストレージ)

NSTextStorageはNSMutableAttributedStringのサブクラスです。テキスト表現としては、前項で解説しているNSAttributedStringと同じ機能を持っています。テキストの内容に変更があると、前述のレイアウトマネージャに通知します。レイアウトマネージャはこの通知を受けて、テキストを再レイアウトを行います。
なお、1つのテキストストレージは、1つまたは複数のレイアウトマネージャを持つことができます。テキストストレージが複数のレイアウトマネージャを持つことは、異なるレイアウトに同一コンテンツを表示できることを意味します。この際、一方のレイアウトでテキストを変更したら、もう一方のレイアウトには即座に反映されます。

また、NSTextStorageはクラスクラスタです。サブクラスを作成する際には独自のストレージが必要となるほか、以下に示すプリミティブメソッドをすべてオーバーライドする必要があります(ソースコード37、38)。なお、クラスクラスタに関する詳細は、Appleの「Objective-C プログラミング概念」などを参照してください。

[ソースコード37] NSAttributedStringのプリミティブメソッド

- (NSString *)string;
- (NSDictionary *)attributesAtIndex:(NSUInteger)index
                     effectiveRange:(NSRangePointer)aRangel;

[ソースコード38] NSMutableAttributedStringのプリミティブメソッド

- (void)replaceCharactersInRange:(NSRange)aRange withString:(NSString *)aString;
- (void)setAttributes:(NSDictionary *)attributes range:(NSRange)aRange;
著者
西方 夏子(にしかた・なつこ)

ソフトウェアエンジニア。大手電機メーカーにおける組込みソフトウェアの開発を経て、現在は個人でiOS向けのアプリケーションを開発している。代表作であるローン計算アプリ「iLoan Calc」は、個人の方のみならず、多くの不動産業、金融業の方からも愛用されている。『iPhoneアプリ開発エキスパートガイド iOS6対応』(共著・インプレスジャパン刊)、『上を目指すプログラマーのためのiPhoneアプリ開発テクニック iOS 7編』(共著・インプレスジャパン刊)などの執筆にも携わり、現在は執筆業を中心にアプリ開発と育児を両立中。

連載バックナンバー

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています