Environment: macOS 15.2 (24C101) with Xcode 16.2 (16C5032a)
Goal: I am trying to build a simple IMKInputController-based input method.
Problem: My .app bundle registers successfully and I can select it as an input source. When selected, it blocks keyboard input, but my handle method does not seem to execute or produce output. I have placed NSLog statements in my controller's init and handle methods.
Code for the controller:
import InputMethodKit
// The IMKTextInput protocol is provided by the framework.
// We don't need to define our own bridging protocol for this test.
public class HelloWorldController: IMKInputController {
public override init!(server: IMKServer!, delegate: Any!, client inputClient: Any!) {
super.init(server: server, delegate: delegate, client: inputClient)
NSLog("HelloWorldIME: Controller has been initialized.")
}
public override func handle(_ event: NSEvent!, client sender: Any!) -> Bool {
NSLog("HelloWorldIME: handle() method was called.")
// ================== FINAL FIX APPLIED HERE ==================
// 1. First, we ensure the client is a fundamental Objective-C object.
guard let clientObject = sender as? NSObject else {
NSLog("HelloWorldIME: Error - client object is not an NSObject.")
return false
}
NSLog("HelloWorldIME: Successfully cast client to NSObject.")
// 2. Now that we have an NSObject, we can safely check if it responds to the selector.
let selector = #selector(IMKTextInput.insertText(_:replacementRange:))
if !clientObject.responds(to: selector) {
NSLog("HelloWorldIME: Error - client object does not respond to the insertText selector.")
return false
}
NSLog("HelloWorldIME: Client responds to insertText. Preparing to insert text.")
// 3. Since we've confirmed it responds, we can now safely treat it as an IMKTextInput
// and call the method.
let client = clientObject as! IMKTextInput
let stringToInsert = "A"
let replacementRange = NSRange(location: NSNotFound, length: 0)
client.insertText(stringToInsert, replacementRange: replacementRange)
NSLog("HelloWorldIME: Called insertText with string '\(stringToInsert)'. Action complete.")
// ========================================================
return true
}
}