Text Kitによるテキストレイアウト(前編)[2ページ目]

これらのクラス関係の例を下図に示します(図16)。この例は、テキストストレージが持つテキストコンテンツを、2ページ(もしくは2カラム)に分割して表示する場合のクラス関連図です。そのため、レイアウトマネージャが2つ存在しています。

図16: Text Kitのクラス関係(複数ページに分割表示する例)

UITextViewのインスタンスを生成すると、そのUITextViewに関連付けされたNSTextContainer、NSLayoutManager、NSTextStorageのインスタンスが生成され、プロパティを通してアクセス可能となります。ただし、これらのプロパティはreadonlyであるため、生成後に変更することはできません。
テキストビューに自前のテキストコンテナを対応付けるには、以下のメソッドを利用してコードからUITextViewのインスタンスを生成します。

[ソースコード39] 自前のテキストコンテナを持つUITextViewを生成するメソッド

- (instancetype)initWithFrame:(CGRect)frame
                textContainer:(NSTextContainer *)textContainer;

レイアウトマネージャを利用すると、位置座標から表示されている文字を取得することが可能です。これをヒットテストと呼びます。例えば、タップ位置(タッチ終了位置)に表示されている文字は、下記のコードで取得できます。

[ソースコード40] 座標から文字インデックスを取得(ヒットテスト)

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    CGPoint locationInView = [touch locationInView:self.textView];
  
    NSTextContainer *textContainer = self.textView.textContainer;
    NSLayoutManager *layoutManager = self.textView.layoutManager;
    // テキストコンテナの座標系に変換
    CGPoint locationInContainer =
    CGPointMake(locationInView.x - self.textView.textContainerInset.left,
                locationInView.y - self.textView.textContainerInset.top);
    // 文字インデックスを取得
    NSUInteger charIndex = [layoutManager characterIndexForPoint:locationInContainer
                                                 inTextContainer:textContainer
  fractionOfDistanceBetweenInsertionPoints:NULL];

  // テキストストレージから該当文字を取得
  NSString *charString =
  [[self.textView.textStorage string] substringWithRange:NSMakeRange(charIndex, 1)];
}

上記の処理内容はシンプルです。まずtextViewの座標系におけるタッチ位置を取得します。得られた位置をテキストコンテナの座標系に変換します。このとき、UITextViewが持つtextContainerInsetプロパティの値を用います。テキストコンテナの座標系でのタッチ位置が得られたら、あとはそこから文字インデックスを取得できます。

この記事のキーワード :

人気記事トップ10

人気記事ランキングをもっと見る

企画広告も役立つ情報バッチリ! Sponsored

ClickHouse Cloudが実現した広告運用SaaS「ATOM」のデータ基盤革新、パフォーマンスを向上しながら、運用負荷とコストを削減 11月11日 6:20 AIで開発が加速する時代、品質保証はどう変わる? Tricentisが示すAIエージェント活用の実像 11月9日 6:45 悪用までの猶予が「1分」に迫るフロンティアAI時代に開発と本番を貫く脆弱性管理が必要 10月29日 8:30 欧州CRA対応とSBOM運用。AI生成コードのOSS混入問題の対策とは ――スニペット単位で検出する「FossID」「Insignary Clarity」によるSBOM運用 9月16日 6:40 PostgreSQLからTiDBへ、稼働中SaaSで進める段階的DB移行の実践と再設計への展望 9月7日 6:30 機能安全開発におけるGoogleTestの活用を支援!「Parasoft C/C++test CT」で実現する効率化&AI連携 4月14日 6:30 【CNDW2025】Grafanaが明かす「オブザーバビリティの哲学」ー最小限の労力で実用的なインサイトを得るには 1月23日 6:30 【CNDW2025】プロダクト急増に備える基盤刷新 ーウェルスナビがECSからEKSへの移行で得た知見とは 1月15日 6:30 【CNDW2025】250環境を5人で運用、構築時間は30分に ーKINTOテクノロジーズが語るインフラ基盤組織の作り方 2025年12月18日 6:30 新たな自動化で熱視線! AIエージェントの「推論能力」を支える2つのコンポーネントとは? 2025年11月28日 6:30