App Extension Programming Guide: Custom Keyboard
自定義鍵盤取代了系統鍵盤,用戶需要能力,如一種新的文本輸入方法,或者在IOS中不支持的語言中輸入文本的能力。自定義鍵盤的基本功能很簡單:響應輕敲、手勢或其他輸入事件,并在當前文本輸入對象的文本插入點以非屬性NSCOPE對象的形式提供文本。
用戶選擇自定義鍵盤后,它就成為用戶打開的每個應用程序的鍵盤。為此,您創建的鍵盤至少必須提供某些基本特征。最重要的是,您的鍵盤必須允許用戶切換到另一個鍵盤。#了解用戶對鍵盤的期望為了了解用戶對自定義鍵盤的期望,研究系統鍵盤的快速、響應和能力。而且它從不中斷用戶的信息或請求。如果您提供需要用戶交互的功能,則不將它們添加到鍵盤,而是添加到包含鍵盤的應用程序中。
iOS用戶期待的鍵盤功能
這是iOS用戶期望的一個特性,每個自定義鍵盤必須提供:切換到另一個鍵盤的方法。在系統鍵盤上,這個按鈕顯示為一個稱為“環球鑰匙”的按鈕。在iOS 8和以后,系統為您的“下一個鍵盤”鍵提供了一個特定的API,描述了提供切換到另一個鍵盤的方法。系統鍵盤根據當前文本輸入對象的UIKeyboradType特性提供適當的密鑰集或布局。例如,在郵件中的“to”字段中插入點時,系統鍵盤周期密鑰更改:當按下并保持該鍵時,可以從一組頂級域后綴中挑選。像這樣設計你的鍵盤。IOS用戶也希望自動大寫:在標準文本字段中,區分大小寫語言的句子的第一個字母是自動大寫的。
下面列出這些特性和其他特性
- 基于鍵盤類型特征的適當布局和特征
- 自動校正與建議
- 首字母自動大寫
- 雙擊空格插入句號
- 大寫鎖定
您可以決定是否實現這些特性;沒有列出任何列出的功能的專用API,因此提供它們是一個競爭優勢。
自定義鍵盤不可用的系統鍵盤功能
您的自定義鍵盤無法訪問設置應用程序(設置>通用鍵盤)中的大多數通用鍵盤設置,例如自動大寫和啟用大寫鎖定。您的鍵盤也不能訪問字典重置功能(設置>通用>重置>重置鍵盤字典)。為了給用戶提供靈活性,創建一個標準設置包,如在IOS設置包中的首選項和設置編程指南中所描述的。然后,您的自定義設置出現在與鍵盤相關的設置中的鍵盤區域中。有某些文本輸入對象,您的自定義鍵盤沒有資格輸入。首先是任何安全的文本輸入對象。這樣的對象是通過其secureTextEntry屬性設置為yes定義的,并通過將類型化的字符表示為點來區分。當用戶在安全文本輸入時,系統會臨時用系統鍵盤替換您的自定義鍵盤。當用戶在非安全文本輸入時,您的鍵盤會自動恢復。您的自定義鍵盤也不適合鍵入所謂的電話簿對象,例如聯系人中的電話號碼字段。
這些輸入對象專門用于由電信運營商指定的一組字母數字字符構成的字符串,并通過具有以下兩種鍵盤類型特征的一種或另一種來標識:
- UIKeyboradTypePhonePad
- UIKeyboradTypeNamePhonePad
當用戶在電話盤點擊時,系統會臨時用適當的標準鍵盤替換您的鍵盤。當用戶在一個不同的輸入對象中點擊,通過其類型特征請求一個標準鍵盤時,你的自定義鍵盤自動恢復。應用程序開發人員可以選擇拒絕在他們的應用程序中使用所有自定義鍵盤。例如,一個銀行應用程序的開發者,或者一個必須符合美國HIPAA隱私規則的開發者,可能會這樣做。這樣的應用程序遵守UIApplicationDelegate委托協議中的application:shouldAllowExtensionPointIdentifier:方法(返回no),因此總是使用系統鍵盤。
因為自定義鍵盤只能在其UIInputViewControoler對象的主視圖內繪制,所以無法選擇文本。文本選擇是在使用鍵盤的應用程序的控制之下。如果該應用程序提供了編輯菜單界面(如剪切、復制和粘貼),則鍵盤無法訪問它。自定義鍵盤不能在插入點附近提供內聯自動更正控件。自定義鍵盤,像所有的應用程序擴展在IOS 8,沒有訪問設備麥克風權限,因此聽寫輸入是不可能的。
最后,不可能在自定義鍵盤的主視圖的頂部邊緣顯示關鍵圖形,因為系統鍵盤在iPhone上點擊并保持頂部行中的鍵。
自定義鍵盤的快速啟動
這一節讓你快速瀏覽API來構建鍵盤。圖8-1顯示了運行鍵盤中的一些重要對象,它們來自一個典型的開發流程。
自定義鍵盤模板(在IOS應用程序擴展“目標模板組”)包含UIInputViewController的子類,該類用作鍵盤的主視圖控制器。該模板還包括“下一個鍵盤”鍵的基本實現,它調用類的UIInputViewController的advanceToNextInputMode方法。將對象(如視圖、控件和手勢識別器)添加到輸入視圖控制器的主視圖(在其輸入視圖屬性中),如圖8-1所示。與其他應用程序擴展一樣,目標中沒有窗口,因此本身也沒有根視圖控制器。
模板的info.plist預先配置鍵盤所需的最小值。在鍵盤目標的info.plist中查看NSExtensionAttributes字典鍵。在配置自定義鍵盤的info.plist時,描述了配置鍵盤的鍵。
默認情況下,鍵盤沒有網絡訪問,不能與包含它的應用程序共享內容。若要啟用這些操作,請將info.plist中的RequestOpenAccess密鑰的值設置為“是”。這樣擴展鍵盤沙盒,是為用戶信任而做。
輸入視圖控制器符合與文本輸入對象的內容交互的各種協議:
- 要插入或刪除文本響應觸摸事件,請使用UIKeyInput協議中的insertText方法和deleteBackward方法。在輸入視圖控制器的textDocumentProxy屬性上調用這些方法,該屬性表示當前文本輸入對象,并且符合UITextDocumentProxy協議。
- 在使用deleteBackward方法時,若要獲取您需要刪除多少文本的數據,請從TextDocumentProxy屬性的documentContextBeforeInput屬性獲取插入點附近的文本上下文。你可以刪除適當的文本,例如,單個字符,或返回到空白字符的所有內容。要用語義單位刪除,如單詞、句子或段落,請使用CFStringTokenizer Reference中描述的函數,并參考相關文檔。注意,每種語言都有自己的符號化規則。
- 為了控制插入點位置,例如支持在向前方向上的文本刪除,請調用UITextDocumentProxy協議的adjustTextPositionByCharacterOffset方法。
- 為了響應活動文本對象內容的變化,或者響應用戶發起的插入點位置的變化,使用UITextInputDelegate協議中的方法。若要呈現適用于當前文本輸入對象的鍵盤布局,請響應對象的UIKeyboardType屬性。
對于支持的每個特性,相應地更改自己的主視圖的內容。為了在自定義鍵盤中支持多個語言,您有兩個選項:
- 每個語言創建一個鍵盤,每個都作為一個單獨的目標添加到一個公共的包含應用程序中。
- 創建一個單一的多語言鍵盤,動態地切換它的主要語言若要動態切換主語言,請使用UIInputViewController類的primaryLanguage屬性。根據你想要支持的語言數量和你想要提供的用戶體驗,選擇最有意義的選項。每個自定義鍵盤(獨立于其RequestOpenAccess鍵的值)都可以通過UILexicon類訪問基本的自動更正詞典。利用這個類,連同你自己設計的詞典,在用戶輸入文本時提供建議和自動更正。UILexicon對象包含來自不同來源的單詞,包括:
- 用戶地址簿數據庫中未配對的名字和姓氏
- 在設置> 通用 >鍵盤>快捷方式列表中定義的文本替換
- 常用詞詞典
您可以使用自動布局調整自定義鍵盤的主視圖的高度。默認情況下,根據屏幕大小和設備方向,定制鍵盤的大小與系統鍵盤匹配。自定義鍵盤的寬度總是由系統設置為等于當前屏幕寬度。若要調整自定義鍵盤的高度,請更改其主視圖的高度限制。
定制鍵盤的開發要點
有兩點非常重要:
- **信任**。您的自定義鍵盤使您能夠訪問用戶的類型,因此您和用戶之間的信任是必不可少的。
- **切換到下一個鍵盤**。讓用戶切換到另一個鍵盤的功能是鍵盤用戶界面的一部分;您必須在鍵盤中提供一個。
用戶信任的設計
創建自定義鍵盤時首先考慮的是如何建立和維護用戶信任。這種信任取決于您對隱私最佳實踐的理解和了解如何實現它們。對于鍵盤來說,以下三個方面對于建立和維護用戶信任尤為重要:
- 輸入數據的安全性?用戶希望他們的按鍵轉到他們正在鍵入的文檔或文本字段,而不是在服務器上存檔或用于不明顯的目的。
- 適當和最小化使用其他用戶數據?如果您的鍵盤使用其他用戶數據,例如從位置服務或地址簿數據庫,您就有責任向用戶解釋和演示這些好處。
- 準確性?將輸入事件轉換為文本的準確性本身不是一個隱私問題,但它影響信任:每一個字輸入,用戶都會看到代碼的準確性。
為了設計信任,首先考慮是否請求開放訪問。盡管開放式訪問使自定義鍵盤有很多可能,但它也增加了您的職責(見表8-1)。
如果你建立一個鍵盤,沒有打開的訪問權限,系統確保擊鍵不能發送回你或任何其他地方。如果你的目標是提供正常的鍵盤功能,請使用非網絡鍵盤。由于其受限的沙盒,非網絡鍵盤使您在滿足蘋果的數據隱私指南和獲得用戶信任。如果啟用打開訪問(如為自定義鍵盤配置info.plist所描述的),各種可能性打開,但您的職責也會增加。與開放存取相關聯的每個鍵盤功能都作為開發人員承擔責任,如表8-2所示。一般來說,以最大可能的尊重對待用戶數據,并且不使用對用戶不明顯的任何目的。開放存取鍵盤及其包含的應用程序可以向您的服務器發送擊鍵數據,這使得您可以將計算資源應用于觸摸事件處理和輸入預測等功能。如果您使用此功能,不要將接收到的擊鍵或語音數據存儲在提供給用戶的文本所需的時間之外,或提供您向用戶解釋的功能。在使用開放存取鍵盤功能時,請參閱表8-2以了解您的額外職責。
提供切換到另一個鍵盤的方法
當一個以上的鍵盤被啟用時,系統鍵盤包括一個允許用戶切換鍵盤的地球鍵(見圖8-2)。您的自定義鍵盤可能需要類似的“下一個鍵盤”鍵。要確定您的自定義鍵盤是否需要顯示“下一個鍵盤”鍵,請檢查輸入視圖控制器上的needsInputModeSwitchKey屬性。如果是真的,你的鍵盤應該包括這個鍵。要讓系統切換到另一個鍵盤,請調用UIInputViewController類的advanceToNextInputMode方法。
系統從用戶啟用的鍵盤列表中選擇合適的“下一個”鍵盤;沒有API來獲得啟用的鍵盤列表或選擇切換到特定鍵盤。XCODE自定義鍵盤模板包括advanceToNextInputMode方法作為下一個鍵盤鍵的動作。為了獲得最佳用戶體驗,將你的“下一個鍵盤”鍵放在靠近系統鍵盤位置的同一屏幕位置。
開始編寫自定義鍵盤
在本節中,您將學習如何創建自定義鍵盤,根據您的目標配置它,并在iOS模擬器或設備上運行它。在替換系統鍵盤時,您還可以了解一些UI因素。###使用XCODE自定義鍵盤模板創建鍵盤及其包含的應用程序的步驟與其他應用程序擴展略有不同。本節介紹如何獲得和運行基本鍵盤。
在包含應用程序中創建自定義鍵盤
1. 在Xcode中,choose File > New > Project,選擇ios application模板中的單例模式
2. 點擊next
3. 命名工程,點擊next
4. 選定創建位置,點擊next
5. 選擇 File> New > Target,然后選擇Application Extension中的Custom Keyboard 模板,點擊next
6. 命名
7. 點擊結束
現在可以選擇自定義鍵盤組名稱,如在設置中購買的鍵盤列表中所示,如下所述。
設定鍵盤組名稱
1. 在XCODE項目導航器中,選擇包含在App的支持文件文件夾中的應用程序的info.plist。屬性列表編輯器打開,顯示文件的內容。
2. 將光標懸停在“束名”行上,然后單擊出現的“+”按鈕。這將創建一個新的空屬性列表行并選擇它的鍵字段。
3. 開始鍵入綁定顯示名稱,當名稱自動完成時,按返回。
4. 在同一行中的值字段中雙擊以獲得一個游標,然后輸入所需的鍵盤組名稱。
5. 選擇文件>保存以保存對屬性列表文件的更改。表8- 3總結了自定義鍵盤的UI字符串,可以在鍵盤的info.plist中配置UI及其包含的應用程序。現在,您可以在iOS模擬器或設備上運行基于模板的鍵盤,以探索其行為和能力。
為自定義鍵盤配置info.plist文件
特定于自定義鍵盤的信息屬性列表(info.plist文件)鍵使您靜態聲明鍵盤的顯著特征,包括其主語言,以及它是否需要打開訪問。要檢查這些鍵,請打開一個XCODE項目,其中添加了自定義鍵盤目標模板。現在在項目導航器中選擇info.plist文件(iinfo.plist文件在鍵盤目標的支持文件文件夾中)。
這些密鑰中的每一個都在應用程序擴展鍵中解釋。使用NSExtensionAttributes字典中的鍵來表示自定義鍵盤的特性和需求,如下所示:
IsASCIICapable-默認情況為NO,此布爾值表示自定義鍵盤是否可以將ASCII字符串插入到文檔中。如果您提供一個鍵盤類型專門用于UIKeyboardTypeASCIICapable鍵盤類型的特性,則將該值設置為YES。
PrefersRightToleft-默認情況為NO,該布爾值也表示自定義鍵盤是否為右到左語言。如果鍵盤的主語言從右到左,將此值設置為YES。
primaryLanguage -這個字符串值,en-us(默認為美國英語)使用模式-表示鍵盤的主要語言。
RequestOpenAccess-默認情況為NO,此布爾值表示自定義鍵盤是否希望將沙盒擴大到基本鍵盤所需的范圍之外。如果您通過將該鍵的值設置為YES,請求打開訪問,則您的鍵盤將獲得以下功能,每個功能在用戶信任方面具有伴隨的責任:
- 訪問位置服務、地址簿數據庫和相機滾動,每個用戶需要在第一次訪問時允許
- 選擇使用包含鍵盤的應用程序的共享容器,它可以在包含應用程序的應用程序中提供自定義的詞典管理UI
- 能夠通過網絡發送擊鍵、其他輸入事件和數據來進行服務器端處理
- 使用UIPastedboard
- 播放音頻的能力,包括使用playInputClick方法點擊鍵盤
- 訪問iCloud,您可以使用它,例如,確保鍵盤設置和自定義自動更正詞典在用戶擁有的所有設備上都是最新的
- 通過包含應用程序訪問游戲中心和應用程序購買
- 如果設計了支持移動設備管理的鍵盤(MDM),則可以使用托管應用程序
在考慮是否將RequestOpenAccess密鑰的值設置為YES時,請務必閱讀用戶信任的設計,它描述了您尊重和保護用戶數據的職責。