天天看點

使用 Xamarin 開發 iOS 鍵盤擴充(含網絡通路)

作為一位 .NET 技術的死忠,開發 iOS 應用當然要使用 Xamarin 啦!

本文用我的閱讀的文檔和實踐為素材,介紹如何使用 Xamarin 開發一個 iOS 的鍵盤擴充。

你可以在 Walterlv.CloudKey

搭建環境

本文不會花篇幅來講如何搭建 Xamarin iOS 開發的環境,不然這篇文章就沒有重點。

于是,請閱讀這一篇來了解如何搭建 Xamarin iOS 的開發環境:

  1. 安裝調試工具:Mac 部分 Xamarin開發(Mac開發)環境搭建 - 簡書
  2. 安裝調試工具:Windows 部分 vs2017開發IOS(vs2017 xamarin 連接配接mac) - ManGo.XYZ - CSDN部落格
  3. 申請開發者賬号:https://developer.apple.com/register/,閱讀這裡了解坑
  4. 準備一根 Type-C 到 Lightning 的資料線,用于 Mac 從 Mac 部署到真機進行調試

你需要了解的 iOS 鍵盤擴充的背景知識

了解以下背景知識,有助于我們接下來開發的時候少踩一些坑。當然我不會在這裡說 iOS 應用開發的所有背景知識,隻會說與 iOS 鍵盤擴充相關的部分。

  1. iOS 鍵盤擴充是 iOS 擴充的一種,而 iOS 擴充是 iOS 8.0 才開始引入的概念。
  2. iOS 擴充需要有一個 iOS 普通應用作為容器一起打包;是以,你需要建立兩個項目來完成 iOS 鍵盤擴充的開發。
    • 在後文,我們将直接使用 iOS 容器應用來描述這個概念
    • 擴充的包辨別符(Bundle Identifier)必須以容器應用的包辨別符字元串作為開頭
  3. iOS 擴充和 iOS 容器應用會被視為兩款完全不同的應用,互相之前不能共享任何資料。
    • 如果真的要共享資料,就需要像其他兩款不同應用共享資料一樣的處理方式
  4. iOS 鍵盤擴充預設是不能通路網絡的,你需要聲明允許通路網絡,并獲得使用者的同意才行。

建立 iOS 鍵盤擴充項目

第一步:建立 Xamarin.Forms 項目。

這個不用太在意裡面的實作,因為它隻是我們的“容器項目”(前面有介紹)。實際上在本文我們完全不會碰這個項目裡面的代碼,隻是為了配置我們的 iOS 應用包而已。未來你可以在這個容器應用裡面做鍵盤的個性化設定。

使用 Xamarin 開發 iOS 鍵盤擴充(含網絡通路)

然後,選擇 iOS 平台。

我們隻需要 iOS 端。因為對于鍵盤,不同系統的實作差異很大,之間共享的代碼隻能是非鍵盤部分的代碼了。

使用 Xamarin 開發 iOS 鍵盤擴充(含網絡通路)

第二步:建立 iOS 鍵盤擴充項目

使用 Xamarin 開發 iOS 鍵盤擴充(含網絡通路)
使用 Xamarin 開發 iOS 鍵盤擴充(含網絡通路)
使用 Xamarin 開發 iOS 鍵盤擴充(含網絡通路)

當你建立完之後,你會看到三個不同的項目。

你可能發現 Walterlv.KeyboardExtension.Keyboard 項目有些奇怪,裡面有 Main 函數和 AppDelegate,按道理這是一個主程式包。然而實際測試中單獨有這個項目是跑不起來的(這可能是一個 Bug,如果修複了,請在下面評論或者郵件告知我,謝謝了)。

于是,Main 和 AppDelegate 這兩個檔案是可以删除的。如果你強迫症,就删掉吧。當然不删掉也不影響,不過我删掉了。

第三步:引用 iOS 鍵盤擴充項目

在 iOS 容器應用上面添加鍵盤擴充項目作為引用。

使用 Xamarin 開發 iOS 鍵盤擴充(含網絡通路)
使用 Xamarin 開發 iOS 鍵盤擴充(含網絡通路)

如果你感興趣去檢視 Walterlv.KeyboardExtension.iOS 項目中對 Walterlv.KeyboardExtension.Keyboard 項目的引用節點的話,你會發現 Xamarin 已經自動為這個項目标記上了

<IsAppExtension />

。隻有加上了 AppExtension 标記,Xamarin 才會把這個項目作為 iOS 擴充項目進行打包。

<ProjectReference Include="..\..\Walterlv.KeyboardExtension.Keyboard\Walterlv.KeyboardExtension.Keyboard.csproj">
    <Project>{d6f006e7-3c98-4b97-b2d5-4d2e3bc2f945}</Project>
    <Name>Walterlv.KeyboardExtension.Keyboard</Name>
    <IsAppExtension>true</IsAppExtension>
    <IsWatchApp>false</IsWatchApp>
</ProjectReference>           

複制

在以上三個步驟完成之後,理論上你是可以正常編譯此項目的。

使用 Xamarin 開發 iOS 鍵盤擴充(含網絡通路)

配置包資訊

iOS 應用的包資訊存儲在 plist 中。是以在這一節,你需要正确配置兩個項目的 plist。

沒錯!是兩個項目。還記得前面背景知識裡面我們說到容器項目和擴充項目就是兩個不同的應用嗎?

配置 plist 的方法,就是在 Visual Studio 裡面輕按兩下這個檔案。

按照下圖這樣配置:

使用 Xamarin 開發 iOS 鍵盤擴充(含網絡通路)

說明:

  1. Application Name 對應 plist 中的 CFBundleDisplayName 屬性,也就是應用的顯示名稱。
    • 對于容器應用,就是 iOS 圖示下面的名稱,對于鍵盤,就是切換鍵盤的時候所用的名稱。
    • 下圖中 iOS 應用圖示下面的名稱 CloudKeyboard 就是我在 Walterlv.CloudKeyboard 項目中的容器應用的名稱。
    • 下圖中在 iOS 切換鍵盤時,Cloud 就是我在 Walterlv.CloudKeyboard 項目中的鍵盤名稱。
  2. 擴充項目的 Bundle Identifier 名稱必須以容器項目的 Bundle Identifier 名稱作為字首。
    • 如果不滿足要求,部署時擴充将不會生效。
使用 Xamarin 開發 iOS 鍵盤擴充(含網絡通路)
使用 Xamarin 開發 iOS 鍵盤擴充(含網絡通路)

至此,你的項目可以直接編譯了。如果你有真機部署環境,都可以直接部署到真機上看效果了。

真機部署調試

本文不會花篇幅來講如何真機部署調試,不然這篇文章就沒有重點。

但是你可以閱讀:使用 Xamarin 在 iOS 真機上部署應用進行調試

當然這是 Mac 版本的(畢竟我在 Windows 上實際也沒有成功真機調試過,我是 git 同步到 Mac 上用 Visual Studio for Mac 來真機調試的)。

隻是你需要注意做這些内容:

  1. 你需要同意一份開發者證書(不然打不開應用):
    • 設定 -> 通用 -> 裝置管理 -> [自己的開發者賬号] -> 信任
  2. 還需要打開這個鍵盤(不然看不到鍵盤):
    • 設定 -> 通用 -> 鍵盤 -> 添加新鍵盤… -> [選擇我們剛剛開發的鍵盤]

下面是我部署到真機上之後,在亮暗兩種不同的界面下的鍵盤截圖(就是上面的項目,沒有改任何代碼):

使用 Xamarin 開發 iOS 鍵盤擴充(含網絡通路)

處理鍵盤的文字輸入、倒退和确定

我們把 Walterlv.CloudKeyboard.iOS.Extension 也就是那個鍵盤擴充項目删除得隻剩下 KeyboardViewController.cs 了,我們也隻需要在這個類中寫代碼而已。

要控制文字輸入,就是使用

TextDocumentProxy

執行個體。我們的

KeyboardViewController

繼承自

UIInputViewController

,于是我們能夠在類中直接使用

TextDocumentProxy

執行個體。

在光标處插入文字:

TextDocumentProxy.InsertText("walterlv");           

複制

如果要插入換行或者确認輸入,則使用:

TextDocumentProxy.InsertText("\n");           

複制

在光标處删除前一個字:

TextDocumentProxy.DeleteBackward();           

複制

如果想要清空文本,則可以循環删除:

while (TextDocumentProxy.HasText)
{
    TextDocumentProxy.DeleteBackward();
}           

複制

你沒有辦法删除後一個字,也不能擷取到使用者輸入的任何内容。

關于換行,特别注意:如果文本框被設定為發送或者其他非換行的功能,那麼使用

InsertText

單獨插入換行時才能正常執行這些功能。如果調用此代碼之前還有其他的插入文字,那麼最終就隻會是換行,而不會執行其他的功能。實際上我在這一點上踩了坑,導緻在 QQ 或者其他工具中隻能實作換行,而無法發送消息。

iOS 的鍵盤有不同種類的确認,需要鍵盤針對

TextDocumentProxy.

我還沒有找到辦法直接完成文本的輸入,例如執行确認按鈕的邏輯。而确認按鈕有這麼些不同的情況:

// 我當然是寫 C# 語言版本的枚舉,而不是 Object-C 版本的啦。
public enum UIReturnKeyType : long
{
    Default,
    Go,
    Google,
    Join,
    Next,
    Route,
    Search,
    Send,
    Yahoo,
    Done,
    EmergencyCall,
    Continue,
}           

複制

添加鍵盤的網絡通路支援

允許完全通路(包括網絡)

純本地的鍵盤很難在打字速度上獲得優勢,各種主流的輸入法也通常借助網絡來提高自身的輸入準确度。

使用者需要在鍵盤設定裡面開啟鍵盤的“允許完全通路”才能讓對應的輸入法獲得網絡通路的權限。如果使用者沒有給權限,那麼網絡通路的時候鍵盤擴充就會出現異常,然後閃退。

使用 Xamarin 開發 iOS 鍵盤擴充(含網絡通路)

然而如果你去我們剛剛開發的輸入法中看,你會發現我們的輸入法沒有提供這樣的選項可以設定。那麼如何能夠添加這個設定以便進行網絡通路呢?

方法是修改鍵盤擴充項目的 Info.plist 檔案。這個時候的修改,我們就不能使用 Visual Studio 中自帶的 plist 編輯器了,我們需要使用文本編輯器來編輯 plist 檔案。

在你的 Info.plist 檔案中找到

RequestsOpenAccess

屬性,然後将它分值從

false

改為

true

<key>RequestsOpenAccess</key>
--  <false/>
++  <true/>           

複制

這個屬性設為

true

之後,再次部署,你将可以在你的鍵盤設定裡面看到“允許完全通路”的設定項。開啟之後,你就能在你的鍵盤裡面通路網絡了。

允許通路 http 不安全網絡

一般來說你不用閱讀這一小節的内容。因為現在基本上各種服務都已經是 https 了,http 基本已經絕迹。但是如果你需要臨時部署一個服務,沒來得及申請 https 證書的話,那麼就需要使用本小結的内容讓你的鍵盤支援 http 的通路。

繼續打開你的鍵盤擴充項目的 Info.plist 檔案,在根字典的最後添加一個完整的字典屬性

NSAppTransportSecurity

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
    <key>NSExceptionDomains</key>
    <dict>
        <key>walterlv.com</key>
        <dict>
            <key>NSExceptionAllowsInsecureHTTPLoads</key>
            <true/>
            <key>NSIncludesSubdomains</key>
            <true/>
        </dict>
    </dict>
</dict>           

複制

特别注意,裡面的

walterlv.com

需要換成你自己的域名。是域名,不用包含端口号。

這樣,你就能在鍵盤中通路 http://walterlv.com 了。

本文總結

  1. 本文介紹了使用 Xamarin 開發 iOS 鍵盤插件的背景知識。
    • 必須了解這些知識才不會在一些不太重要的坑上耗費太長時間。
  2. 本文教大家如何開發 iOS 鍵盤插件,主要是項目組織以及寫代碼。
    • 至少,使用文本編寫出來的代碼,能夠在不作任何修改的情況下部署到真機。(實際上我們隻在 KeyboardViewController.cs 中加了寥寥幾行代碼。)
  3. 本文不涉及到搭建開發環境,不涉及如何連接配接真機調試。
    • 你可能需要配合這些部落格才能完成部署以及調試:
    • Xamarin開發(Mac開發)環境搭建 - 簡書
    • vs2017開發IOS(vs2017 xamarin 連接配接mac) - ManGo.XYZ - CSDN部落格

如果你還遇到了一些其他詭異的問題:

  • 歡迎閱讀 使用 Xamarin 開發 iOS 應用中需要注意的若幹個問題。
  • 歡迎在評論區評論或者向我發郵件。

參考資料

  • iOS Extensions in Xamarin.iOS - Xamarin - Microsoft Docs
[iOS 8 Custom Keyboard Tutorial: How to Create A Third-Party Keyboard Extension iPhone and iOS App UI Design Templates](http://www.appdesignvault.com/ios-8-custom-keyboard-extension/#a_aid=mdev)
  • 如何使用Xamarin開發iOS輸入法 - 簡書
  • ios - Make HTTP Request from Custom Keyboard App Extension - Stack Overflow
  • ios - Transport security has blocked a cleartext HTTP - Stack Overflow
  • iOS - 輸入框有值時才能點選鍵盤上的returnkey(enablesReturnKeyA… - 簡書
  • objective c - Handling Return key in iOS 8 keyboard extension - Stack Overflow
  • objective c - Handling Return key in iOS 8 keyboard extension - Stack Overflow
  • iphone - iOS keyboard with “Go” button instead of return - Stack Overflow
  • Custom Keyboards - Extensions - iOS - Human Interface Guidelines - Apple Developer
  • Creating a Custom Keyboard In IOS… – Swift India – Medium

本文會經常更新,請閱讀原文: https://blog.walterlv.com/post/develop-ios-keyboard-exte

本作品采用 知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協定 進行許可。歡迎轉載、使用、重新釋出,但務必保留文章署名 呂毅 (包含連結: https://blog.walterlv.com ),不得用于商業目的,基于本文修改後的作品務必以相同的許可釋出。如有任何疑問,請 與我聯系 ([email protected]) 。