Swift 使用 InputMethodKit 寫輸入法

如何在 iOS 上寫一款輸入法?這個問題已經被很多人解答過了。你可以輕易通過 Google 找到一篇詳細的教程。但是,在 macOS 上寫一款輸入法就沒那麼簡單了。

好吧,嚴格來講,是指用 Swift 在 macOS 上寫一款輸入法很難。主要的原因是 從來沒有人做過這件事情 。

目前能夠獲取的資料,除了蘋果官方的 API 說明(一點用也沒有),以及官方的 demo(很詳細但過時了,而且還是用 OC 寫的。)之外,幾乎什麼都沒有了。

現在我寫這篇文章就是來總結一下,如果你想用 Swift 3 開始寫一個 macOS 能用的輸入法,需要繞過哪些坑。

Info.plist中

對於輸入法來說,需要在這個文件當中做一些額外的配置,大部分的配置你只需要對比蘋果官方推出的 Demo 即可 —— 它們大部分都是正確的。

有一點沒有說明的地方在於,你的 identifier 需要按照一定的格式來寫——也就是說,這個字段中必須包含 輸入法 這個關鍵詞。

比如說,我的輸入法叫這個名字 LogInputMac ,那麼我就不能寫成 .logcg.LogInputMac ,這樣的話 macOS 就不能把它識別為輸入法(就算放進了 /資源庫/輸入 方法/ 也不行),你必須把 輸入法 這個關鍵字加進去,而且最好不要放在最後,應該放在前三個點(.)之內。比如說像我這樣: .logcg.輸入法.LogInputMac

另外,對於 Swift,你還需要做一下單獨的操作,如果你就這樣將編譯好的 APP 放進 /資源庫/輸入 方法/ ,那麼雖然 macOS 可以識別輸入法,但實際上不會有任何作用——你的 IMKInputController 是完全不會被加載的。

這是因為 macOS 找不到你的 IMKInputController 類,為此,我們應該把 InputMethodServerControllerClassInputMethodServerDelegateClass 字段的內容改成以 $(PRODUCT_MODULE_NAME). 前綴的形式,也就是說,應該寫成這樣:

使用斯威夫特與InputMethodKit工作

使用斯威夫特與InputMethodKit工作

AppDelegate.swift

由於 InputMethodKit 的運作方式與普通 APP 不同,我們需要在應用一開始就初始化 IMKServer 類,大多數人的第一反應就是把它放到 在applicationDidFinishLaunching(_ : ) 裡去執行,正相反,由於 Swift 沒有 main 函數,我們可以直接把它聲明為全局變量而不需要先聲明再給全局變量賦值,我們把它寫在 在applicationDidFinishLaunching 裡,同時你也可以在這裡做一些額外的準備工作,比如拷貝一下詞庫:

打印(_:)

由於 Swift 不像 OC 都是用 NSLog 來輸出控制台消息,大家都還是喜歡用 打印(_:) 來實現打印終端內容——對於輸入法來說,你不能這樣調試程序了。

如果你直接用 Xcode 執行你的輸入法,是沒有任何效果的。想要測試輸入法,就必須將它放到 /資源庫/輸入 方法/ 中然後加載。這樣的話,即使你使用 Xcode attach 到輸入法的進程,也不會得到任何終端輸出。

這時候就需要使用 的NSLog ,它可以方便地將輸入法的消息輸出到控制台中,這樣你就可以打開控制台,然後查看進程的信息了。

調試

對於輸入法來說,在 osx 下它是一個全局的東西,所以你很難去對它進行 debug,總之,我們還是可以讓開發過程盡可能的舒服,首先,你需要更改輸入法目錄的權限:

這樣就可以讓 Xcode 直接編譯到目錄了,然後,在 Xcode 裡編輯 target,

建立 設置 > 所有 > 建立 地點 > -組態 建立 製品 路徑 > 調試

把對應的值改為: /圖書館/輸入 方法

這樣你就可以直接編譯,在系統偏好設置中添加一次即可,以後編譯都能事實生效,不用來回重啟或者註銷了。

值得注意的是:千萬不要添加斷點……

 

延伸閱讀

最後,這裡放上唯一一篇我能找到的中文的對 InputMethodKit 介紹的文章,大家可以參考一下(很遺憾,我並沒有用到這篇文章,因為找到它的時候我已經踩過了以上所有的坑)。

半年後,我又重啟了這個項目,而且又找到了另外一篇非常有用的文章:macOS下基於IMK的輸入法(一)——創建步驟

另外,我想你可能還是無法成功的對照 OC 代碼來轉換 Swift 項目,那麼我把這個對應蘋果官方“NumberInput_IMKit_Sample-NumberInput_0”的 Swift 項目打包上傳,如果需要的話可以下載參考

本文由 落格博客 原創撰寫:落格博客 » Swift 使用 InputMethodKit 寫輸入法

轉載請保留出處和原文鏈接:https://www.logcg.com/archives/2078.html

關於作者

R0uter

如非聲明,本人所著文章均為原創手打,轉載請註明本頁面鏈接和我的名字。

註釋

    1. 你好朋友,抱歉回复的晚了,前段時間比較忙……
      合作可以有,不過我只能以外包、兼職等方式和你合作,不做技術入股後期分紅的方案,如果你能接受的話,咱就進一步談談,看看是一次性付費我按你需求開發交付,還是按工作時間付費進行開發。
      當然,將來開發完成後,維護工作和開發新功能等費用,咱們可以另外再談或者以後再談的。

      至於開發的代碼,可以完全歸你所有,如果有涉及到我現在再用的算法相關代碼,我們可以另行討論(如果可能,也可以授權互換等等……

  1. 我不知道哪裡錯了,每次啟動都會出現[IMKServer _createConnection]: *無法*註冊NSConnection名稱= com.logcg.inputmethod_Connection錯誤,您是否遇到過這問題,怎麼解決的

    1. 檢查你代碼裡的 NSConnection name,也就是 IMKServer(name: kConnectionName, bundleIdentifier: .主要.bundleIdentifier) 裡的實際參數和 Info.plist 裡 輸入方法連接名稱中設置的是否完全一致。

  2. 感謝這個見地的帖子! 我也對著你提到我想寫使用雨燕的輸入法這些絆腳石. 這是很可悲的是有沒有可用的輸入法這是寫在斯威夫特學習的榜樣. 我編譯您上傳名為FlyMac的例子時有錯誤. 它也沒有你在這個帖子中提到的編輯喜歡它不使用 $(PRODUCT_MODULE_NAME) 在InputMethodServerControllerClass財產. 這將是一個很大的幫助我,如果你上傳的工作示例.

    非常感謝!

  3. 你好我很高興,我發現您的博客, 我真的發現你意外, 當我
    一直在尋找在AOL的其他東西, 無論如何,我
    現在這裡wokuld只想說感謝
    很多關於一個了不起的帖子和周圍激動人心的博客 (我也很喜歡這個主題/設計),
    我沒有時間去broiwse這一切在momernt但我
    救它,也增加了你的RSS源, 所以當我有時間我會回來的TTO閱讀更多, 請不要
    保持了出色的工作.

發表評論

您的電子郵件地址不會被公開. 必填字段標 *