データや画像の検出と埋め込み
NSURL *url = [NSURL URLWithString:@"http://www.apple.com/"]; NSAttributedString *linkText = [[NSAttributedString alloc] initWithString:@"link to apple website" attributes:@{NSLinkAttributeName: url}];
上記コードの通り、NSLinkAttributeNameを用いて、リンクを埋め込みたいテキストに対して特定のURLを関連付けることができます。
また、属性を使用して埋め込むリンクは、UITextViewがデフォルトで検出可能なデータタイプに限定する必要はありません。例えば、「メッセージ」アプリは、スキーム「sms」で開くことができるため、メッセージ送信のリンクを埋め込むことも可能です(ソースコード34)。
下記コードで、「Send SMS message」がリンクとして検出され、タップすると「メッセージ」アプリが起動します。
NSURL *smsUrl = [NSURL URLWithString:@"sms:090-1234-5678"]; NSAttributedString *sendSmsText = [[NSAttributedString alloc] initWithString:@"Send SMS message" attributes:@{NSLinkAttributeName: smsUrl}];
なお、NSLinkAttributeName属性を指定して埋め込んだリンクも、UITextViewのlinkTextAttributesに設定されているアピアランスが適用されます。また、UITextViewのデリゲートが設定されていれば、タップ時にtextView:shouldInteractWithURL:inRange:メソッドが呼ばれます。
続いて、属性付きテキストを用いてテキスト内に画像を埋め込む方法を解説します。
NSAttachmentAttributeName属性を用います。値はNSTextAttachmentオブジェクトで指定します。例えば、テキストの先頭に画像を埋め込むには、属性付きテキストを生成します(ソースコード35)。属性付きテキストの生成には、NSAttributedStringのattributedStringWithAttachment:クラスメソッドが利用できます。
// 画像を元にNSTextAttachmentを生成 NSTextAttachment *textAttachment = [[NSTextAttachment alloc] init]; textAttachment.image = [UIImage imageNamed:@"apple"]; // 画像の位置とサイズを調整 textAttachment.bounds = CGRectMake(0, -2, image.size.width, image.size.height); // 画像を表示する属性付きテキストを生成 NSAttributedString *attachementText = [NSAttributedString attributedStringWithAttachment:textAttachment]; // 属性付きテキスト内に画像を埋め込み NSMutableAttributedString *imageText = [[NSMutableAttributedString alloc] initWithString:@"Apple リンゴ"]; [imageText insertAttributedString:attachementText atIndex:6];
上記コードで画像を埋め込んだ表示結果を示します(図15)。
画像の表示位置は、テキストのベースラインが画像の左下になるように調整されます。表示位置やサイズを変更したい場合には、NSTextAttachmentのboundsプロパティを利用します。
属性付きテキストを利用して埋め込んだ画像は、タップが検出されると画像のコピーもしくはカメラロールへの保存が促されます(デフォルト処理)。この処理のカスタマイズは、リンクやデータ検出時と同様に、UITextViewDelegateのメソッドを利用します(ソースコード36)。
- (BOOL)textView:(UITextView *)textView shouldInteractWithTextAttachment: (NSTextAttachment *)textAttachment inRange:(NSRange)characterRange { // 画像タップ時の処理 return YES; // YES:デフォルトの処理をする、NO:デフォルトの処理をしない }
なお、属性付きテキストによる画像の埋め込みは、UITextView以外のオブジェクト(UILabelなど)でも使用可能です。ただし、画像タップの検出はUITextView上の表示のみです。