-
ジェン文字でアプリに表情を追加
アプリ内でのジェン文字(Genmoji)の使い方に精彩を与える方法を習得しましょう。ジェン文字を含むテキストをレンダリング、格納、やり取りする方法を概説します。カスタムテキストエンジンを使用するアプリにジェン文字のサポートを追加する手法もご紹介します。
関連する章
- 0:00 - Introduction
- 0:37 - Express yourself
- 1:17 - Emoji enhancements
- 2:17 - NSAdaptiveImageGlyph
- 3:15 - Adopting in your app
- 8:01 - Compatibility
- 9:10 - Advanced usage
- 10:33 - Wrap-up
リソース
関連ビデオ
WWDC24
-
ダウンロード
こんにちはエンジニアのAaronです Input Experienceチームに所属しています 今日は絵文字を使って アプリの表現力を高める 新しいエキサイティングな方法を ご紹介したいと思います このセッションでは 最新の絵文字の機能を探り カスタム絵文字を送信するための新しいAPIを 紹介し 絵文字をアプリに簡単に取り入れる方法を 紹介します その後 互換性に関する注意事項や カスタムテキストレンダリングの 高度な使用例についても深く掘り下げます 絵文字はいたるところにあります それには理由があります
絵文字はとても表現豊かで テキストの段落全体をたった1つの絵文字で 置き換えることもできます
汎用性もあります 1つの絵文字では伝えきれない場合も 適切な組み合わせを見つければ 完璧に表現できます!
絵文字はテキストなので テキストと 組み合わせるとさらにパワフルになります 画像と違って 絵文字は文章の一部なので 周囲のテキストに合った 表示にすることができます Appleは今年 絵文字をさらに良くするための 様々なアップデートを行います その1つが よく使われる標準の絵文字を パーソナライズされたコンテンツと 組み合わせて 絵文字のように使える 新しい絵文字キーボードです
ステッカー ミー文字 アニ文字に加え オリジナルの絵文字を作るための まったく新しい方法を利用できます ジェン文字(Genmoji)です
なかなかクールな犬ですね みなさんの中には こう考える方もいるでしょう 従来の絵文字は実際には画像ではなく プレーンテキストとして送信される 標準化されたUnicode文字のリストなので 他のテキストコンテンツと同様 適切な画像が表示されるかどうかは 表示するデバイスのフォントに依存すると しかし ジェン文字のような パーソナライズされた画像は ラスタ化された固有のビットマップなので Unicodeテキスト文字では記述できません どんな仕組みになっているのでしょうか NSAdaptiveImageGlyphは ジェン文字などのパーソナライズされた画像を 標準の絵文字と同じように扱うための まったく新しいAPIです NSAdaptiveImageGlyphは 標準の画像フォーマットを基盤としており 正方形のアスペクト比で 複数の解像度をサポートしています 追加のメタデータとして グローバルに一意で安定した識別子 アクセシビリティのために使用できる コンテンツの説明 画像の適切なレイアウトと配置を可能にする 調整メトリックスなどがあるため 通常のテキストと一緒に使用したり フォーマットしたりできます ジェン文字は単独で使うことも テキストと組み合わせて使うこともできます フォーマット コピー 貼り付けのほか ステッカーとして送信することもできます
リッチテキストに対応していれば いずれの環境でもジェン文字を含む 表現豊かな画像がすべてサポートされます
それでは アプリでジェン文字をサポートする方法が いかに簡単か見ていきましょう NSAdaptiveImageGlyphは TextViewでネイティブでサポートされます そのため アプリがすでに リッチテキストに対応していれば supportsAdaptiveImageGlyphを 有効にするだけで簡単に始められます
iOSでは pasteConfigurationなど 画像に対応する貼り付けの ターゲットアクションがすでに テキストビューで構成されていれば ジェン文字と適応型画像グリフのサポートが デフォルトで有効になるため その構成も必要ありません macOSでは importsGraphicsを テキストビューで宣言して同じことができます では例を見てみましょう
ユーザーがペットとの思い出を 記録して共有できるアプリがあるとします メインテキスト領域は すでにリッチテキストビューになっていて リッチテキストデータで 永続モデルに格納されます そのため ジェン文字のサポートは デフォルトで有効になり機能しています
SecureCodingやPasteboardなど システムのシリアル化フレームワークはすべて NSAdaptiveImageGlyphをネイティブで サポートするように更新されているからです 実際 テキストコンテンツがすでに NSAttributedStringsで格納されていれば 他にやることはなく あとは自分を表現するだけです 他のリッチテキストと同じように テキストビューのコンテンツを そのままRTFDデータオブジェクトに シリアル化してデータベースに格納します コンテンツを再度表示する時は 逆のプロセスで 前に格納したデータから 属性付き文字列を作成します とても簡単です 簡単ではありますが ジェン文字はUnicodeではないため メールアドレスや電話番号のような テキストのみの項目には 適さない場合があることに注意してください 一方でブログ投稿やタイトル メッセージなどという ユーザーが作成するコンテンツはまさに 画像グリフのサポートによって 生き生きとしたものになります 例えば カスタムの絵文字を使って タイトルを目立たせることができます データはプレーンテキストとして 格納されているので 最終的にバックエンドサーバで共有して Webブラウザで表示することができます そのためにはどうすればよいでしょうか 1つの方法として プレーンテキストなどの 非RTFのデータストアを使用する時は インライン画像と同じ方法で 画像グリフを扱います 例えば 該当するテキスト位置にある Unicode付加文字を 画像グリフの識別子の参照とともに プレーンテキストデータフィールドに格納し その画像を画像ストアに追加できます contentIdentifierは 一意で安定しているため この識別子を使って すでに画像グリフを格納している場合は 再度格納する必要はありません 属性付き文字列を分解して 組み立て直す例については 本セッションに付属のコードをご覧ください これらの変更によって タイトルにジェン文字が追加され メインエントリとリストにも表示されます では 前に述べた Webインターフェイスはどうでしょうか これ以上ないほど簡単です HTMLで画像を表示するには 先ほどと同じ 範囲データのメソッドを使用して RTFDに変換しますが 今回は HTMLドキュメントタイプをリクエストします これにより 相互互換性のあるHTMLが出力され 「apple-adaptive-glyph型」に対応する Webkitなどの高度なエンジンで 標準の絵文字のように 画像がテキストにインラインで表示されます 画像グリフに対応していないエンジンの場合 この代替画像が代わりに表示されます この代替テキストは NSAdaptiveImageGlyphの コンテンツ説明のものであり ブラウザで最終的にどのソースを 表示するかに関係なく適用されます アプリでコミュニケーション通知を 利用する場合は ジェン文字や他の画像グリフを 通知に含めることもできます これには新しいUNNotificationAttributed MessageContext APIを使用します 必要なのは プッシュ通知のペイロードに リッチテキスト表現を含めることだけで それに画像グリフも含めることができます リッチテキストの解析 アセットのダウンロード 属性付き本文の作成 通知コンテンツの更新には Notification Service Extensionの使用をおすすめします 画像グリフを含む属性付き文字列から 通知メッセージを作成し attributedContentとして渡すだけで コンテキストが作成されます そのコンテキストでリクエストを更新し 最後にハンドラを呼び出します NSAdaptiveImageGlyphの 高度な使用法を紹介する前に アプリで重要となる 互換性に関する注意事項について 少しお話しします
画像グリフは一緒に表示されるテキストと同様 何らかの意味を伝えるものであり 適切に伝わらないと 意味が失われたり変わったりしてしまうため サポートされていない場合の フォールバックの扱いに注意が必要です 大切なのは 重要な情報が 簡単に破棄されないようにすることです アプリがインライン画像に 対応していない場合は contentDescriptionのテキスト表現を 使用することを検討してください また そもそも互換性がない場合なら 対応していないシステムではドキュメントを 開かないことを検討してください
RTFD形式で格納された画像グリフは 画像グリフを認識しないものも含め いずれのリッチテキストビューとも 下位互換性をもつようにエンコードされます サポートされていない環境で RTFドキュメントを共有する場合 古いOSで実行されている 旧バージョンのアプリなどでは 画像グリフが自動的にフォールバックして 標準のテキストアタッチメントに戻ります ジェン文字を使うにはリッチテキストを サポートするのが一番簡単かもしれませんが サードパーティのデータ形式や まったく独自のテキストエンジンでも 画像グリフを完全にサポートできます テキストビュー コンテンツの編集可能な WebView SwitfUIのテキストなど すべてのAppleプラットフォームの 既存のUIテキスト要素が 画像グリフに対応していることに加えて TextKitやCoreTextのような Appleの既存のフレームワークを基に 構築した独自のテキストエンジンでも 更新されたテキストレンダリングAPIを 利用して ジェン文字の独自のソリューションを 提供できます CoreTextには カスタムの印字ソリューション向けに NSAdadptiveImageGlyphを アダプティブ画像プロバイダとして使用して 現在のフォントのメトリックスに基づいて 適切なタイポグラフィの範囲を照会できる メソッドが用意されています この方法で 現在のコンテキスト中の所定の 位置に画像をレンダリングすることもできます その仕組みを詳しく見てみましょう CTFontGetTypographicBoundsFor AdaptiveImageProviderは 横方向の配置に必要な 詳しい幅などのメトリックスを返します ベースライン上のグリフの原点を 基準とした相対位置です 描画する時は CTFontDrawImageFromAdaptiveImage ProviderAtPointが その範囲内に画像を配置します 必要なことはこれだけです
今回は すべてのAppleプラットフォームで利用できる いくつかの新しい絵文字の機能について 簡単にご紹介しました まったく新しい絵文字キーボードや ジェン文字を使った独自の絵文字の作成 さらにNSAdaptiveImageGlyphを使用して アプリで表情豊かな画像をサポートする いくつかの方法も説明しました 標準のリッチテキストビューを使う場合も または完全に独自の 印字ソリューションを使う場合も ぜひ最新のSDKをチェックしてください ジェン文字を使えばアプリで まったく新しい自己表現の可能性が 簡単に開かれることがわかるでしょう ご視聴ありがとうございました
-
-
3:30 - Enable support for NSAdaptiveImageGlyph in a UITextView
let textView = UITextView() textView.supportsAdaptiveImageGlyph = true
-
4:41 - Read and write attributed string for serialization
// Extract contents of text view as an attributed string let textContents = textView.textStorage // Serialize as data for storage or transport let rtfData = try textContents.data(from: NSRange(location: 0, length: textContents.length), documentAttributes: [.documentType: NSAttributedString.DocumentType.rtfd]) // Create attributed string from serialized data let textFromData = try NSAttributedString(data: rtfData, documentAttributes: nil) // Set on text view textView.textStorage.setAttributedString(textFromData)
-
6:08 - Decompose and recompose an attributed string
// Decompose an attributed string func decomposeAttributedString(_ attrStr: NSAttributedString) -> (String, [(NSRange, String)], [String: Data]) { let string = attrStr.string var imageRanges: [(NSRange, String)] = [] var imageData: [String: Data] = [:] attrStr.enumerateAttribute(.adaptiveImageGlyph, in: NSMakeRange(0, attrStr.length)) { (value, range, stop) in if let glyph = value as? NSAdaptiveImageGlyph { let id = glyph.contentIdentifier imageRanges.append((range, id)) if imageData[id] == nil { imageData[id] = glyph.imageContent } } } return (string, imageRanges, imageData) } // Recompose an attributed string func recomposeAttributedString(string: String, imageRanges: [(NSRange, String)], imageData: [String: Data]) -> NSAttributedString { let attrStr: NSMutableAttributedString = .init(string: string) var images: [String: NSAdaptiveImageGlyph] = [:] for (id, data) in imageData { images[id] = NSAdaptiveImageGlyph(imageContent: data) } for (range, id) in imageRanges { attrStr.addAttribute(.adaptiveImageGlyph, value: images[id]!, range: range) } return attrStr }
-
6:30 - Convert NSAttributedString to HTML
// Converting NSAttributedString to HTML let htmlData = try textContent.data(from: NSRange(location: 0, length: textContent.length), documentAttributes: [.documentType: NSAttributedString.DocumentType.html])
-
7:33 - Support Genmoji in communication notifications
func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { ... let message: NSAttributedString = _myAttributedMessageStringWithGlyph let context = UNNotificationAttributedMessageContext(sendMessageIntent: sendMessageIntent, attributedContent: _message) do { let messageContent = try request.content.updating(from: context) contentHandler(messageContent) } catch { // Handle error } }
-
9:45 - Render NSAdaptiveImageGlyph in custom typesetting solution
// Find typographic bounds for image in NSAdaptiveImageGlyph let provider = adaptiveImageGlyph let bounds = CTFontGetTypographicBoundsForAdaptiveImageProvider(font, provider) // Draw it at the typographic origin point on the baseline CTFontDrawImageFromAdaptiveImageProviderAtPoint(font, provider, point, context)
-
-
特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。