← 所有文章

Genmoji 與 NSAdaptiveImageGlyph:應用程式如何顯示使用者產生的內嵌表情符號

Genmoji 是 Apple Intelligence 自訂表情符號功能的使用者端名稱:使用者輸入描述,系統產生一個內嵌的類表情符號圖像,結果與 Unicode 表情符號一同出現在文字中。開發者端的介面是 NSAdaptiveImageGlyph,這是 iOS 18+ 的類別,用於表示屬性化文字中的自適應內嵌圖像1。Genmoji 是 NSAdaptiveImageGlyph 實例的來源之一;處理屬性化文字的應用程式必須支援此類別才能顯示 Genmoji(以及未來 Apple 推出的任何自適應圖像字符內容)。

本文將對照 Apple 的文件來逐步走過 API。框架是「現有的文字處理應用程式必須做什麼才能正確顯示 Genmoji」,因為大多數在 UITextView 中接受使用者輸入文字的應用程式都需要選擇啟用自適應圖像字符,使用者的 Genmoji 才能呈現出來,而持久化端則有容易被忽略的序列化影響。

TL;DR

  • NSAdaptiveImageGlyph(iOS 18+)是包裝自適應圖像加上識別中繼資料的資料型別。從系統鍵盤輸入的 Genmoji 會以嵌入在屬性化文字中的 NSAdaptiveImageGlyph 實例形式抵達2
  • supportsAdaptiveImageGlyph 宣告於 UITextInput 協定上;UITextView 遵循此協定,因此該屬性可透過 textView.supportsAdaptiveImageGlyph = true 設定。預設值為 false;若不選擇啟用,使用者輸入的 Genmoji 將無法呈現。
  • 自適應圖像字符需要 TextKit 2。仍使用 TextKit 1 的應用程式無法正確呈現 NSAdaptiveImageGlyph。針對 iOS 18+ 的新應用程式應預設使用 TextKit 2。
  • NSAttributedString 透過 NSAttributedString.Key.adaptiveImageGlyph 屬性攜帶自適應圖像字符。初始化方法 NSAttributedString(adaptiveImageGlyph:attributes:) 會建構一個包含單一字符的屬性化字串3
  • 持久化與往返處理需要謹慎。純文字儲存會完全剝除 Genmoji;富文字格式(RTFD、含擴充功能的 Markdown、嵌入圖像資料的 HTML)能保留它們。

NSAdaptiveImageGlyph 攜帶的內容

NSAdaptiveImageGlyph 是具有四個識別屬性的資料包裝器2

  • imageContent: Data 圖像資料本身,格式由 contentType 宣告。
  • contentIdentifier: String 字符實例的唯一識別碼。用於去重以及系統的內部快取。
  • contentDescription: String 描述字符的替代文字。會顯示無障礙標籤或將字符傳送給不支援字符之接收者的應用程式會使用此屬性。
  • contentType: UTType 一個類別層級的型別屬性,公開 Apple 用於自適應字符的圖像格式(HEIC 變體)。進行序列化的應用程式會檢查此屬性以驅動格式感知的處理。

對標準 Genmoji 而言,資料通常為數十 KB。多個尺寸使用 HEIC 的自適應圖像功能編碼於同一個圖像檔案中;系統會根據呈現的情境挑選正確的尺寸。

UITextView 中啟用自適應圖像字符

選擇啟用只需單一屬性1

import UIKit

let textView = UITextView()
textView.supportsAdaptiveImageGlyph = true
// Also requires TextKit 2 (default on UITextView for iOS 16+
// when constructed via Interface Builder or modern initializer)

若未設定 supportsAdaptiveImageGlyph = true,使用者輸入的 Genmoji 會顯示為佔位字元(系統無法呈現該字符)。設定此屬性會同時啟用呈現以及系統鍵盤的「Genmoji」分頁,讓使用者能在文字檢視內建立自訂 Genmoji。

SwiftUI 原生的 TextFieldTextEditor 目前未提供 supportsAdaptiveImageGlyph 修飾符。需要自適應圖像字符呈現的 SwiftUI 應用程式會將 UITextView 包裝在 UIViewRepresentable 中,並在底層檢視上設定 supportsAdaptiveImageGlyph = true。社群套件如 GlyphMeThat 提供現成的橋接。

TextKit 2 是關鍵承載

NSAdaptiveImageGlyph 需要 TextKit 2 的版面架構4。TextKit 1(隨原始 NSTextStorage/NSLayoutManager/NSTextContainer 模型一起推出的舊版文字引擎)無法正確呈現自適應圖像字符;字符會顯示為通用佔位符,或完全無法版面配置。

應用程式有三種狀態:

iOS 18+ 上的新應用程式。 預設使用 TextKit 2。透過 Interface Builder 或 init(frame:textContainer:) 初始化的 UITextView 在 iOS 16+ 上預設使用 TextKit 2。新程式碼可免費取得。

仍使用 TextKit 1 的舊應用程式。 必須進行遷移。對於繼承 NSLayoutManager、覆寫版面相關委派方法或直接使用較舊 NSTextStorage 的應用程式,TextKit 2 遷移並非簡單之事。Apple 的 TextKit 遷移指南涵蓋了這個路徑;對於僅有簡單 UITextView 用法的應用程式,遷移大多是自動的。

混合式應用程式。 部分應用程式會嵌入 WKWebView 進行 HTML 編輯,同時搭配 UITextView 進行純文字編輯。WKWebView 透過自身的呈現路徑(非 TextKit)處理自適應圖像字符,因此混合式應用程式可能會有一個介面支援 Genmoji 而另一個不支援。請記錄此行為;當一個編輯器支援自訂表情符號而另一個會剝除時,使用者會察覺到。

NSAttributedString 的整合

自適應圖像字符透過 NSAttributedString.Key.adaptiveImageGlyph 屬性流經屬性化字串3

import UIKit

// Construct an attributed string containing a single adaptive image glyph
let glyph: NSAdaptiveImageGlyph = ...
let attrString = NSAttributedString(
    adaptiveImageGlyph: glyph,
    attributes: [
        .font: UIFont.systemFont(ofSize: 17)
    ]
)

// Concatenate with surrounding text
let composed = NSMutableAttributedString(string: "Look at this ")
composed.append(attrString)
composed.append(NSAttributedString(string: " I just made!"))

此模式可組合:字符位於文字之中,文字位於更多文字之中。系統會自動處理版面配置(包括字符針對周圍文字字型的自適應大小調整)。

讀取時,迭代 NSAttributedString.adaptiveImageGlyph 屬性會在字符出現的位置回傳 NSAdaptiveImageGlyph 實例:

attributedString.enumerateAttribute(
    .adaptiveImageGlyph,
    in: NSRange(location: 0, length: attributedString.length)
) { value, range, _ in
    if let glyph = value as? NSAdaptiveImageGlyph {
        // process glyph + range
    }
}

進行篩選、轉換或持久化文字的應用程式會使用此列舉來尋找字符,並決定如何處理它們。

持久化與序列化

純文字儲存(String、UTF-8 檔案)無法保留自適應圖像字符。代表屬性化文字中字符的 Unicode 佔位字元會被序列化為 U+FFFC(物件取代字元)或什麼都沒有,而實際的字符資料會遺失。

若要進行可往返的持久化,應用程式需要富文字格式5

RTFD。 Apple 的富文字加附件格式。可往返自適應圖像字符。備忘錄、郵件(傳送富內容時)以及 TextEdit 都使用此格式。格式較冗長(包含附件的目錄套件)但無損。

HTML 搭配嵌入圖像。 對網路友善。字符會序列化為帶有 base64 編碼資料 URI 的 <img> 標籤。負載較大,但能在大多數支援富文字的接收端運作。

Markdown 搭配擴充功能。 標準 Markdown 沒有自適應圖像字符語法,但擴充方言(含附件支援的 CommonMark、Apple 自家的擴充 Markdown)能攜帶它們。針對任何以 Markdown 為基礎的持久化方案,請記錄方言要求。

透過網路傳送文字(聊天、電子郵件、社群媒體)的應用程式必須決定:端對端保留字符(僅在傳送方與接收方皆為 iOS 18+ 且傳輸支援富文字時可行)、剝除字符並以替代文字(contentDescription)取代,或將字符呈現為系統圖像並嵌入該圖像。正確的選擇取決於受眾與平台。

常見失誤

來自 Genmoji 整合記錄的三種模式:

忘記設定 supportsAdaptiveImageGlyph = true 最常見的錯誤。文字檢視能正常呈現 Unicode 表情符號,但 Genmoji 卻顯示為佔位字元。修正:在每個接受使用者輸入文字的 UITextView/NSTextView 上將該屬性設為 true。SwiftUI 則使用 .supportsAdaptiveImageGlyph(true) 修飾符。

純文字持久化剝除字符。 將文字檢視的內容儲存為 text(純 String)會丟棄 Genmoji。使用者輸入自訂表情符號,在文字檢視中看到它,儲存文件,重新開啟;表情符號不見了。修正:使用支援自適應圖像字符的富文字格式(RTFD、HTML、含附件側通道的自訂格式)將其持久化為 attributedText

網路傳輸悄悄丟失字符。 將外送訊息序列化為純文字的訊息應用程式在傳送時會剝除 Genmoji。接收者看到的是佔位字元或空白。修正:傳送富內容(並確認接收者支援)或對純文字接收者以 contentDescription 取代並將圖像資料作為獨立附件納入。

此模式對 iOS 18+ 應用程式的意義

三項要點。

  1. 在每個文字輸入上設定 supportsAdaptiveImageGlyph = true 接受使用者輸入文字的應用程式預設需要選擇啟用自適應圖像字符。這個單一屬性決定了 Genmoji 能否正常呈現。

  2. 若仍在 TextKit 1,請遷移到 TextKit 2。 TextKit 1 已進入維護模式。新的 iOS 26 時代功能(自適應圖像字符、Writing Tools 的內嵌改寫、Liquid Glass 文字呈現)全都假設使用 TextKit 2。遷移成本確實存在,但替代方案是停留在已棄用的文字引擎上。

  3. 選擇持久化格式時請考量自適應圖像字符。 原生 iOS 儲存使用 RTFD;網路相容儲存使用搭配嵌入圖像的 HTML;高效能應用程式使用具附件側通道的自訂二進位格式。對於使用者會輸入 Genmoji 的應用程式,純文字是錯誤的預設值。

完整的 Apple 生態系列文章:類型化的 App IntentsMCP 伺服器路由問題Foundation Models執行階段與工具 LLM 區別三個介面單一事實來源模式兩個 MCP 伺服器Apple 開發的 hooksLive ActivitieswatchOS 執行階段SwiftUI 內部RealityKit 的空間心智模型SwiftData 結構描述紀律Liquid Glass 模式多平台出貨平台矩陣Vision 框架Symbol EffectsCore ML 推論Writing Tools APISwift TestingPrivacy Manifest無障礙作為平台SF Pro 字體系統visionOS 空間模式Speech 框架SwiftData 遷移tvOS 焦點引擎@Observable 內部SwiftUI Layout 協定自訂 SF SymbolsAVFoundation HDRwatchOS 鍛鍊生命週期iOS 26 中的 App Intents 2.0Image Playground API我拒絕撰寫的內容。中樞位於 Apple 生態系列。如需更廣泛的 iOS 與 AI 代理情境,請參閱 iOS Agent Development 指南

FAQ

我的應用程式如果只用 UITextView,Genmoji 是「免費」就能用嗎?

並非如此。UITextView.supportsAdaptiveImageGlyph 的預設值為 false。應用程式必須將該屬性設為 true 以選擇啟用。一旦啟用,系統鍵盤的 Genmoji 分頁會為使用者出現,且貼上的 Genmoji 也能正確呈現。若未選擇啟用,在他處輸入並貼到文字檢視中的 Genmoji 會顯示為佔位字元。

我需要啟用 Apple Intelligence 才能測試 Genmoji 嗎?

要進行完整的 Genmoji 建立流程,是的。使用者端的 Genmoji 建立流程需要支援 Apple Intelligence 的硬體(iPhone 15 Pro 及更新型號、M 系列 Mac)搭配 iOS 18+ 並啟用 Apple Intelligence。對於 NSAdaptiveImageGlyph 呈現的開發測試,您可以使用範例圖像資料以程式方式建構測試字符實例,並在任何 iOS 18+ 裝置或模擬器上驗證文字檢視的呈現。

將 Genmoji 傳送給使用 iOS 17 的人時會發生什麼事?

若沒有保留字符的富文字傳輸,接收者會看到 contentDescription(替代文字)或佔位字元。現代訊息框架(Apple 的訊息應用程式、近期版本的郵件用戶端)會自動處理回退;自訂協定則需要明確處理。

我可以用程式方式建立 NSAdaptiveImageGlyph 實例嗎?

可以。公開的初始化方法是 init(imageContent: Data),接受預先編碼的 HEIC 自適應圖像資料。contentDescriptioncontentIdentifiercontentType 是從編碼資料中讀取的,而非作為獨立引數傳遞;建立自訂自適應圖像字符的應用程式會準備內嵌中繼資料的 HEIC 負載,然後從該資料建構字符。WWDC 2024 議程 10220(「Bring expression to your app with Genmoji」)涵蓋完整的建立流程。

它如何與 Writing Tools 互動?

Writing Tools(在 Writing Tools API 中說明)會在其改寫輸出中保留自適應圖像字符。選取包含 Genmoji 的文字並請 Writing Tools 改寫的使用者,會得到一份在語意適當位置保留 Genmoji 的改寫結果。透過 UIWritingToolsCoordinator 參與 Writing Tools 的應用程式必須在自訂文字儲存中正確往返處理 NSAdaptiveImageGlyph 實例。

NSAdaptiveImageGlyphNSTextAttachment 有何差異?

NSTextAttachment 是較舊、較廣泛的附件系統,用於屬性化文字中的內嵌非文字內容(圖像、檔案、自訂繪圖)。NSAdaptiveImageGlyph 是 iOS 18 針對類表情符號內嵌圖像的特化版本,可適應周圍字型特徵。兩者皆透過屬性化字串屬性附加,但使用不同的鍵(.attachment.adaptiveImageGlyph)以及不同的呈現路徑(TextKit 1+TextKit 2 對僅 TextKit 2)。針對 Genmoji 風格內容的新程式碼應使用 NSAdaptiveImageGlyph

參考資料


  1. Apple Developer Documentation:supportsAdaptiveImageGlyph。宣告於 UITextInput 協定上的選擇啟用屬性,而 UITextView 遵循該協定;因此同一屬性可透過 textView.supportsAdaptiveImageGlyph 存取。 

  2. Apple Developer Documentation:NSAdaptiveImageGlyph。包裝圖像內容、識別碼、描述與內容類型的資料型別。 

  3. Apple Developer Documentation:NSAttributedString.Key.adaptiveImageGlyphNSAttributedString(adaptiveImageGlyph:attributes:)。自適應圖像字符的屬性化字串整合介面。 

  4. Apple Developer Documentation:TextKit 2 遷移指南。從舊版 TextKit 1 版面引擎遷移到 TextKit 2 的路徑,自適應圖像字符呈現所必需。 

  5. Apple Developer Documentation:NSAttributedString.DocumentType。透過持久化往返處理自適應圖像字符所支援的富文字格式(RTFD、HTML 等)。 

相關文章

Image Playground API: SwiftUI Sheet, Programmatic Image Creator, And Style Control

Image Playground gives apps two paths: the SwiftUI imagePlaygroundSheet modifier and the programmatic ImageCreator API f…

11 分鐘閱讀

Writing Tools API: How Apps Plug Into Apple Intelligence's Writing Layer

iOS 18 introduced Writing Tools. iOS 26 makes adoption a single property for standard text views, and a designed coordin…

14 分鐘閱讀

The Cleanup Layer Is the Real AI Agent Market

Charlie Labs pivoted from building agents to cleaning up after them. The AI agent market is moving from generation to pr…

15 分鐘閱讀