我剛做了一個簡單的測試應用程序,以顯示擊鍵的鍵碼和修飾符。它適用於3個按鍵,然後應用程序崩潰。當它崩潰時,調試控制檯在最後顯示(LLDB)。任何建議可能會造成這種情況?也許某事與線程或指針有關,但我不知道如何解決這個問題。我包含下面的代碼。我非常感謝任何幫助!謝謝!Swift 3 CFRunLoopRun in Thread?
import Cocoa
import Foundation
class ViewController: NSViewController {
@IBOutlet weak var textField: NSTextFieldCell!
let speech:NSSpeechSynthesizer = NSSpeechSynthesizer()
func update(msg:String) {
textField.stringValue = msg
print(msg)
speech.startSpeaking(msg)
}
func bridgeRetained<T : AnyObject>(obj : T) -> UnsafeRawPointer {
return UnsafeRawPointer(Unmanaged.passRetained(obj).toOpaque())
}
override func viewDidLoad() {
super.viewDidLoad()
DispatchQueue.global().async {
func myCGEventCallback(proxy: CGEventTapProxy, type: CGEventType, event: CGEvent, refcon: UnsafeMutableRawPointer?) -> Unmanaged<CGEvent>? {
let parent:ViewController = Unmanaged<ViewController>.fromOpaque(refcon!).takeRetainedValue()
if [.keyDown].contains(type) {
let flags:CGEventFlags = event.flags
let pressed = Modifiers(rawValue:flags.rawValue)
var msg = ""
if pressed.contains(Modifiers(rawValue:CGEventFlags.maskAlphaShift.rawValue)) {
msg+="caps+"
}
if pressed.contains(Modifiers(rawValue:CGEventFlags.maskShift.rawValue)) {
msg+="shift+"
}
if pressed.contains(Modifiers(rawValue:CGEventFlags.maskControl.rawValue)) {
msg+="control+"
}
if pressed.contains(Modifiers(rawValue:CGEventFlags.maskAlternate.rawValue)) {
msg+="option+"
}
if pressed.contains(Modifiers(rawValue:CGEventFlags.maskCommand.rawValue)) {
msg += "command+"
}
if pressed.contains(Modifiers(rawValue:CGEventFlags.maskSecondaryFn.rawValue)) {
msg += "function+"
}
var keyCode = event.getIntegerValueField(.keyboardEventKeycode)
msg+="\(keyCode)"
DispatchQueue.main.async {
parent.update(msg:msg)
}
if keyCode == 0 {
keyCode = 6
} else if keyCode == 6 {
keyCode = 0
}
event.setIntegerValueField(.keyboardEventKeycode, value: keyCode)
}
return Unmanaged.passRetained(event)
}
let eventMask = (1 << CGEventType.keyDown.rawValue) | (1 << CGEventType.keyUp.rawValue)
guard let eventTap = CGEvent.tapCreate(tap: .cgSessionEventTap, place: .headInsertEventTap, options: .defaultTap, eventsOfInterest: CGEventMask(eventMask), callback: myCGEventCallback, userInfo: UnsafeMutableRawPointer(mutating: self.bridgeRetained(obj: self))) else {
print("failed to create event tap")
exit(1)
}
let runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0)
CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, .commonModes)
CGEvent.tapEnable(tap: eventTap, enable: true)
CFRunLoopRun()
}
// Do any additional setup after loading the view.
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
}
非常感謝你這樣的細節答案! – jl303
其實我只是修改了代碼,但現在它似乎沒有觸發事件,也不會引發任何錯誤。看來我不能使用這裏的評論粘貼正確格式的整個代碼。你願意看看修訂後的代碼嗎?對不起,我剛開始學習迅速。 http://pastebin.com/raw/tBJKnrKs – jl303
@ jl303:它在我的測試中有效,但我必須以root身份運行該應用程序,否則輕按創建將失敗。據記載,'tapCreate'只能以root用戶身份運行,或者如果啓用了輔助設備訪問權限才能正常工作。 –