該文檔主要是記錄一些關(guān)于自定義鍵盤的相關(guān)操作,基本用法,注意事項(xiàng)等。
1、關(guān)于自定義鍵盤
1、官方文檔上的定義
? A custom keyboard replaces the system keyboard for users who want capabilities such as a novel text input method or the ability to enter text in a language not otherwise supported in iOS. The essential function of a custom keyboard is simple: Respond to taps, gestures, or other input events and provide text, in the form of an unattributed NSString object, at the text insertion point of the current text input object.
? 由這個定義可以知道,在自定義鍵盤中,你可以像普通應(yīng)用一樣做點(diǎn)擊事件和手勢,或者做鍵盤應(yīng)該有的輸入事件。其中需要注意的是,作為鍵盤輸入的文本,必須是unattributed 的 NSString對象。
2、在自定義鍵盤中至少必須提供的東西
- 一個基本的鍵盤頁面
-
一個切換到別的鍵盤的按鍵
?
3、關(guān)于第三方鍵盤的使用權(quán)限
-
當(dāng)用戶在安全文本(比如將secureTextEntry屬性設(shè)為YES的輸入框)輸入對象中輸入內(nèi)容,iOS系統(tǒng)將暫時強(qiáng)行調(diào)用系統(tǒng)默認(rèn)輸入法,以保證用戶的信息安全。當(dāng)用戶在其他非安全文本輸入對象中輸入時,您的第三方輸入法將被重新調(diào)用。
?
-
第三方輸入法也沒有資格在電話號碼對象中輸入(就像聯(lián)系人應(yīng)用中的號碼字段)。這些輸入對象是專門為電信運(yùn)營商所指定的一個小的數(shù)字字符集而建立的字符串對象,可以通過其是否具有下面任意一個輸入法類型來識別。
1.UIKeyboardTypePhonePad
2.UIKeyboardTypeNamePhonePad
當(dāng)用戶在電話號碼對象中輸入時,系統(tǒng)將暫時強(qiáng)行用相應(yīng)的標(biāo)準(zhǔn)系統(tǒng)輸入法來替換。而當(dāng)用戶在其他的輸入對象中輸入并需要一個標(biāo)準(zhǔn)輸入法適配其類型特點(diǎn)的時候,您的第三方輸入法將會自動恢復(fù)。
?
-
程序開發(fā)者可以選擇禁止所有的第三方輸入法在他們的應(yīng)用中運(yùn)行:使用定義在UIApplicationDelegate協(xié)議中的application:shouldAllowExtensionPointIdentifier:方法(返回值為NO),從而始終使用系統(tǒng)輸入法。
?
-
由于一個第三方輸入法只能在其UIInputViewController對象的主視圖內(nèi)顯示,它將不能夠選擇輸入框中的文字。文本選擇是在應(yīng)用程序的控制下,而第三方輸入法并沒有權(quán)限來訪問它。因此這也就意味著在編輯信息的時候無法移動光標(biāo),粘貼、復(fù)制以及剪切功能將無法使用。
?
-
第三方輸入法和iOS 8.0的所有應(yīng)用程序擴(kuò)展一樣,沒有權(quán)限來訪問設(shè)備話筒,所以聽寫輸入也是不可能實(shí)現(xiàn)的。
?
2、鍵盤項(xiàng)目的創(chuàng)建
1、按照常規(guī)的方式新建一個項(xiàng)目
2、打開新建的項(xiàng)目,在Xcode中選中File —> New —>Target...

3、選中iOS —> Application Extension,然后雙擊右邊的Custom Keyboard跳轉(zhuǎn)到項(xiàng)目創(chuàng)建頁面,輸入Project name并點(diǎn)擊finish,創(chuàng)建成功。

4、創(chuàng)建后,在項(xiàng)目文件的Target中會多一個你創(chuàng)建的Keyboard Extension Target,項(xiàng)目右邊的文件結(jié)構(gòu)中多了一個Keyboard Extension 文件夾,并且文件夾中多了KeyboardViewController(后面說明)文件。 !
Create3.png

3、Custom Keyboard 開發(fā)的相關(guān)說明
下圖顯示了一些運(yùn)行輸入法時的重要元素以及其在一個典型開發(fā)流程中的位置:

1、鍵盤應(yīng)用的入口
KeyboardViewController
? 創(chuàng)建項(xiàng)目以后,xcode提供了一個名為KeyboardViewController的類,它是UIInputViewController的子類,作為鍵盤應(yīng)用的入口。在Info.plist中也的NSExtension —> NSExtensionPrincipalClass 中也可以改成別的繼承自UIInputViewController的ViewController作為入口。
UIInputViewController
? UIInputViewController 提供的常用方法和屬性:
? 1、dismissKeyboard 方法:關(guān)掉鍵盤
? 2、advanceToNextInputMode方法:切換到下一個鍵盤(在自定義鍵盤中必須使用)
? 3、inputView 屬性:相當(dāng)于普通應(yīng)用ViewController.view.(通過測試,UIInputViewController.view 和UIInputViewController.inputView 是同一個對象),可以通過向inputView中添加自定義的Subviews來顯示自定?義的View,給inputView重新賦值為一個自定義的UIInputView對象作為顯示。
? 4、textDocumentProxy 屬性:一個實(shí)現(xiàn)UIKeyInput協(xié)議的對象,通過這個屬性可以實(shí)現(xiàn)判斷是否有輸入,給輸入框插入文本,文本回退等功能(后面解釋)。
? 還有一些方法暫時沒用到過,還有待發(fā)掘。
2、鍵盤輸入等基本操作
? 鍵盤的輸入操作主要是通過UIInputViewController中的textDocumentProxy 屬性提供的幾個主要方法:
-
輸入文本:
? [self.textDocumentProxy insertText:@"hello "];
-
回退操作:
? [self.textDocumentProxy deleteBackward];
-
輸入換行操作:
? [self.textDocumentProxy insertText:@"\n"];
-
輸入的上一個字符
? @property (nonatomic, readonly) NSString *documentContextBeforeInput;
-
即將輸入的一個字符
? @property (nonatomic, readonly) NSString *documentContextAfterInput;
-
將輸入的字符移動到某一位置
? -(void)adjustTextPositionByCharacterOffset:(NSInteger)offset;
? 鍵盤切換操作:
-
關(guān)掉鍵盤,在UIInputViewController中調(diào)用
?[self dismissKeyboard];
-
切換到下一個鍵盤,在UIInputViewController中調(diào)用
[self advanceToNextInputMode];
?
3、修改鍵盤高度
//官方文檔:you can adjust a custom keyboard’s height any time after its primary view initially draws on screen.
//但是如果修改高度的約束的時候會有約束沖突的warning輸出
//有些情況下,如在郵件中退到后臺在回來重新顯示鍵盤時,ViewDidAppear 不會被運(yùn)行到,所以修改約束在 ViewWillAppear中處理
NSLayoutConstraint *heightConstraint =
[NSLayoutConstraint constraintWithItem: self.view
attribute: NSLayoutAttributeHeight
relatedBy: NSLayoutRelationEqual
toItem: nil
attribute: NSLayoutAttributeNotAnAttribute
multiplier: 0.0
constant:kKeyboardHeight];
[self.view addConstraint:heightConstraint];
4、關(guān)于info.plist配置中,一些關(guān)鍵的key說明
1、Bundle display name && Bundle name
? 在Settings > General > Keyboard > Keyboards 中顯示的keyboard 名稱為:
? Keyboard extension Bundle name - Main Application Bundle name
? 在Settings > General > Keyboard > Keyboards > Add New Keyboard…中顯示的名稱為:
? Keyboard extension Bundle name
2、NSExtension

NSExtensionAttributes里面的配置表示著custom keyboard的特點(diǎn)和需求。
- IsASCIICapable--布爾值,默認(rèn)為NO,表示第三方輸入法是否可以向文檔中插入ASCII字符串。如果您的第三方輸入法專門提供UIKeyboardTypeASCIICapable輸入法特性,那么將這個選項(xiàng)設(shè)置為YES。
- PrefersRightToLeft--布爾值,默認(rèn)為NO,表示第三方輸入法使用的是否是一個從右到左的語言。如果您的輸入法主語言是從右到左書寫的,那么講這個選項(xiàng)設(shè)置為YES。
- PrimaryLanguage--字符串值,默認(rèn)為en-US(美國英語),用以表示您輸入法的主語言,使用模式為<語言>-<地區(qū)>。您可以在這個頁面找到某一語言和地區(qū)所對應(yīng)的字符串。
-
RequestsOpenAccess--布爾值,既Full Access(下一節(jié)會說明),默認(rèn)為NO,表示第三方輸入法是否要擴(kuò)展到已滿足基本輸入法需求的沙箱之外。如果開放存取功能,您的輸入法將獲得如下特性,但每一個都有相應(yīng)的責(zé)任:
?
? 1.訪問位置服務(wù)、通信錄數(shù)據(jù)庫以及相機(jī),每一個都需在第一次訪問時獲得授權(quán)。
? 2.可選擇與容納該輸入法的應(yīng)用的共享容器,數(shù)據(jù),資源等,比如在應(yīng)用中可以定制詞匯表,數(shù)據(jù)交流等。
? 3.能夠?qū)⑤斎氲淖址推渌斎胧录蟼髦练?wù)器進(jìn)行處理。
? 4.可以使用剪切板 UIPasteboard對象
? 5.播放音頻,包括按鍵音:通過調(diào)用 playInputClick 方法設(shè)置
? 6.訪問iCloud,例如,能夠確保輸入法的設(shè)置以及您的自動修正詞匯能夠在所有用戶設(shè)備上同步。
? 7.通過包含還輸入法的應(yīng)用,能夠訪問Game Center和應(yīng)用內(nèi)購買。
? 8.能夠和受控應(yīng)用進(jìn)行協(xié)同,如果您使用來設(shè)計該輸入法以支持移動設(shè)備管理(MDM)。
?
5、Full Access
| Full Access | 能力與限制 | 隱私考慮 |
|---|---|---|
| 關(guān)閉 (默認(rèn)) | 1、輸入法可以執(zhí)行一個基本輸入法的所有正常功能; 2、存儲一個常用文本的自動更正和建議到單詞詞典(lexicon) ; 3、有權(quán)使用在設(shè)置中的用戶詞典 ; 4、不能和包含它的應(yīng)用共享數(shù)據(jù); 5、除了自定義鍵盤自身容器意外,無法訪問其他文件系統(tǒng); 6、無法直接或者間接參與iCloud,游戲中心,或在應(yīng)用程序中購買。 | 用戶在使用自定義鍵盤的過程中知道輸入的內(nèi)容只會傳到輸入框所在的app中 |
| 開啟 | 1、除聯(lián)網(wǎng)外的所有自定義鍵盤擁有的功能 2、訪問位置服務(wù)、通信錄數(shù)據(jù)庫以及相機(jī),每一個都需在第一次訪問時獲得授權(quán)。 3、能夠?qū)⑤斎氲淖址推渌斎胧录蟼髦练?wù)器進(jìn)行處理。 4、可選擇與容納該輸入法的應(yīng)用的共享容器,數(shù)據(jù),資源等,比如在應(yīng)用中可以定制詞匯表,數(shù)據(jù)交流等。 5、可以使用剪切板 UIPasteboard對象 6、播放音頻,包括按鍵音:通過調(diào)用 playInputClick 方法設(shè)置 7、訪問iCloud,例如,能夠確保輸入法的設(shè)置以及您的自動修正詞匯能夠在所有用戶設(shè)備上同步。 8、通過包含還輸入法的應(yīng)用,能夠訪問Game Center和應(yīng)用內(nèi)購買。 9、能夠和受控應(yīng)用進(jìn)行協(xié)同,如果您使用來設(shè)計該輸入法以支持移動設(shè)備管理(MDM)。 | 1、用戶知道他們輸入的內(nèi)容可能會提供給鍵盤開發(fā)者 2、必須遵守在App Store審核指南以及iOS開發(fā)者程序許可協(xié)議中的聯(lián)網(wǎng)輸入法指南,可以在App Review Support頁面中找到 |
在鍵盤應(yīng)用中是否獲得Full Access 的方法:
if ([UIPasteboard generalPasteboard]) {
//Full Access
} else {
//No Full Access
}
6、主應(yīng)用程序和鍵盤應(yīng)用的數(shù)據(jù)交流
? 首先需要有開了Full Access之后才能在你主應(yīng)用和鍵盤應(yīng)用之間作數(shù)據(jù)交流,所以在鍵盤的info.plist文件中將RequestsOpenAccess鍵設(shè)置yes,讓用戶在設(shè)置中有Full Access選項(xiàng)
1、創(chuàng)建*.entitlements 文件
-
在Xcode上方的導(dǎo)航欄中,選中File > New >File,然后選中右邊的Resource,再創(chuàng)建一個plist文件。
AddPlist.png 選中-右鍵新創(chuàng)建的plist文件,然后進(jìn)入Finder,將plist文件的后綴由*.plist 改成 *.entitlements,
-
重新將創(chuàng)建的*.entitlements文件拉到項(xiàng)目中去,并勾選上主應(yīng)用和拓展應(yīng)用的Target
AddFile.png
在xcode中打開*.entitlements文件,添加一個array類型的key:com.apple.security.application-groups
-
然后添加一個Item代表Group IdGroupId.png
? 這個GroupID作為主應(yīng)用和Extension應(yīng)用數(shù)據(jù)交流的Identity
-
分別在Main Target 和 Extension Target 的Build setting中,查找Code Signing Entitlements,并在這個key中加入這個文件的相對路徑,如:Test.entitlements文件放在項(xiàng)目文件中的根目錄,則直接寫入Test.entitlements,如果Test.entitlements放在A目錄,則寫入A/Test.entitlements。Entitlements.png
鍵盤和主應(yīng)用通過[[NSUserDefaults alloc] initWithSuiteName:kGroupIdentifier]; 獲得UserDefault對象進(jìn)行數(shù)據(jù)交流。
7、其他問題
待補(bǔ)充



