Swift 4 中的选择器实现
Selector implementation in Swift 4
我正在尝试定义 NSRect 跟踪。在一个新项目中,我只是在 ViewController.swift 文件中添加了几行:
import Cocoa
class ViewController: NSViewController {
let tester = Test()
override func viewDidLoad() {
super.viewDidLoad()
view.addTrackingRect(view.bounds, owner: tester, userData: nil, assumeInside: false)
}
}
class Test: NSObject {
@objc func mouseEntered(with event: NSEvent) {
print("mouseEntered")
}
@objc func mouseExited(with event: NSEvent) {
print("mouseExited")
}
override func responds(to aSelector: Selector!) -> Bool {
print("aSelector: -> \(aSelector) -> \(super.responds(to: aSelector))")
return super.responds(to: aSelector)
}
}
结果是应用崩溃:
aSelector: -> Optional(mouseEntered:) -> false
2017-11-12 00:18:56.204723+0200 test21[19694:1744132] *** Assertion failure in -[NSWindow _setTrackingRect:inside:owner:userData:useTrackingNum:install:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/AppKit/AppKit-1561.10.101/AppKit.subproj/winTrackingAreas.m:408
2017-11-12 00:18:56.207360+0200 test21[19694:1744132] [General] An uncaught exception was raised
2017-11-12 00:18:56.207382+0200 test21[19694:1744132] [General] Window: target of tracking rect doesnt understand -mouseEntered: or -mouseExited messages
所以我的问题是 - 如何定义有效的选择器???
我.
addTrackingRect(_:owner:userData:assumeInside:)
的 Swift 文档非常具有误导性;它说所有者应该回应
to both mouseEntered(with:)
and mouseExited(with:)
.
然而,它真正应该说的是它需要响应选择器 mouseEntered:
& mouseExited:
,因为默认情况下,选择器mouseEntered(with:)
等方法是 mouseEnteredWith:
,因为参数标签是签名的一部分。
所以,要解决这个问题,您可以:
删除参数标签:
class Test : NSObject {
@objc func mouseEntered(_ event: NSEvent) {
print("mouseEntered")
}
@objc func mouseExited(_ event: NSEvent) {
print("mouseExited")
}
// ...
}
手动定义选择器:
class Test : NSObject {
@objc(mouseEntered:) func mouseEntered(with event: NSEvent) {
print("mouseEntered")
}
@objc(mouseExited:) func mouseExited(with event: NSEvent) {
print("mouseExited")
}
// ...
}
我正在尝试定义 NSRect 跟踪。在一个新项目中,我只是在 ViewController.swift 文件中添加了几行:
import Cocoa
class ViewController: NSViewController {
let tester = Test()
override func viewDidLoad() {
super.viewDidLoad()
view.addTrackingRect(view.bounds, owner: tester, userData: nil, assumeInside: false)
}
}
class Test: NSObject {
@objc func mouseEntered(with event: NSEvent) {
print("mouseEntered")
}
@objc func mouseExited(with event: NSEvent) {
print("mouseExited")
}
override func responds(to aSelector: Selector!) -> Bool {
print("aSelector: -> \(aSelector) -> \(super.responds(to: aSelector))")
return super.responds(to: aSelector)
}
}
结果是应用崩溃:
aSelector: -> Optional(mouseEntered:) -> false 2017-11-12 00:18:56.204723+0200 test21[19694:1744132] *** Assertion failure in -[NSWindow _setTrackingRect:inside:owner:userData:useTrackingNum:install:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/AppKit/AppKit-1561.10.101/AppKit.subproj/winTrackingAreas.m:408 2017-11-12 00:18:56.207360+0200 test21[19694:1744132] [General] An uncaught exception was raised 2017-11-12 00:18:56.207382+0200 test21[19694:1744132] [General] Window: target of tracking rect doesnt understand -mouseEntered: or -mouseExited messages
所以我的问题是 - 如何定义有效的选择器???
我.
addTrackingRect(_:owner:userData:assumeInside:)
的 Swift 文档非常具有误导性;它说所有者应该回应
to both
mouseEntered(with:)
andmouseExited(with:)
.
然而,它真正应该说的是它需要响应选择器 mouseEntered:
& mouseExited:
,因为默认情况下,选择器mouseEntered(with:)
等方法是 mouseEnteredWith:
,因为参数标签是签名的一部分。
所以,要解决这个问题,您可以:
删除参数标签:
class Test : NSObject { @objc func mouseEntered(_ event: NSEvent) { print("mouseEntered") } @objc func mouseExited(_ event: NSEvent) { print("mouseExited") } // ... }
手动定义选择器:
class Test : NSObject { @objc(mouseEntered:) func mouseEntered(with event: NSEvent) { print("mouseEntered") } @objc(mouseExited:) func mouseExited(with event: NSEvent) { print("mouseExited") } // ... }