macOS 平台第三方輸入法的生命週期到底是怎樣的?

一轉眼落格輸入法都已經做到第三代了,令人驚訝的是我似乎從來沒有認真的思考過題目中的這個問題。一直以來我先入為主的認為 MACOSiOS版 一樣就是為每個輸入框創建一個輸入法實例,而第三方輸入法的 Controller,全局只有一個,由系統負責 XPC 調用。

後來儘管我發現 Controller 不會在輸入框失去焦點後立即銷毀,但我依舊認為系統會為每個輸入框獲得焦點時生成全新的 Controller。

網上關於 macOS 第三方輸入法的生命週期並沒有很多討論,也是因為上文中我模棱兩可的認知,導致了新版落格輸入法遇到一些難以處理的問題,這次徹底把這個工作搞清楚了。

首先,我們看 IMKInputController 的聲明,裡邊有說:

在輸入法的主函數中分配的 IMKServer 類為客戶端應用程序創建的每個輸入會話創建一個控制器類. 因此,對於每個輸入會話,都有一個相應的 IMKInputController.

所以實際上是每一個“輸入會話”會有一個 Controller 對象,儘管通常我們輸入的時候都只有唯一的輸入框得到焦點(你不可能同時給兩個輸入框打字對吧?)

那麼,這個“輸入會話(input session)”又是個什麼呢?經過我的實際測試,實際上就是對應的 App 了,不論有多少個輸入框,一般一個 App 就會有一個會話,在極端情況下可能會有兩個(這就解釋了一些落格輸入法中切換中英文的奇怪情況),但實際使用的仍然是最新生成的那個。

所以,這麼綜合來看,就可以得到如下結論:

輸入法由系統啟動,進程只有一個。通過系統調用,會為每一個 App 創建一個會話,會話會創建對應的 Controller,然後一般來說這個 Controller 會一直存在,直到這個 App 關閉。

所以這樣一來,你就要小心使用全局變量或者是單件(由於我們確實不可能同時給多個輸入框獲得焦點,所以絕大多數情況下是安全的),因為在某些情況下,一旦發生竟用,則很有可能按鍵信號被多個 Controller 得到,這些共享的全局變量就會受到影響。

不過了解了輸入法的生命週期後,解決方案也不難,其實 Controller 是有激活和反激活回調的,雖然 Controller 對象常駐內存,但我們可以依靠這個回調來判斷用戶當前是不是在用這個 Controller(也就是有沒有在這個輸入框中打字),如果有, FUNC 激活服務器(_ 寄件人: Any!) 會被調用,如果輸入框失去焦點,則 FUNC 停用服務器(_ 寄件人: Any!) 會被調用,我們可以自己創建一個屬性來追踪這個狀態,這樣在需要處理全局通知時,判斷自己如果是未激活,就不要響應即可。落格輸入法 macOS 3 就是這樣解決了中英文切換時靈時不靈的問題。

說實在的,我至今依舊在用一個全局變量追踪當前的活躍 Controller 😅 但最重要的部分已經替換掉了……

 

本文由 落格博客 原創撰寫:落格博客 » macOS 平台第三方輸入法的生命週期到底是怎樣的?

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

關於作者

R0uter

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

發表評論

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