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:,因为参数标签是签名的一部分。

所以,要解决这个问题,您可以:

  1. 删除参数标签:

    class Test : NSObject {
      @objc func mouseEntered(_ event: NSEvent) {
        print("mouseEntered")
      }
    
      @objc func mouseExited(_ event: NSEvent) {
        print("mouseExited")
      }
      // ...
    }
    
  2. 手动定义选择器:

    class Test : NSObject {
      @objc(mouseEntered:) func mouseEntered(with event: NSEvent) {
        print("mouseEntered")
      }
    
      @objc(mouseExited:) func mouseExited(with event: NSEvent) {
        print("mouseExited")
      }
      // ...
    }