Swift 3.0:定时器不为除自身以外的目标触发

Swift 3.0: Timer not firing for target other than self

Timer.scheduledTimer(timeInterval: 5.0, target:self.notificationView, selector: #selector(NotificationView.self.timerFired(_:)), userInfo: nil, repeats: false)

func timerFired(_ timer: Timer) {
        print("Timer Fired")
}

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[_SwiftValue timerFired:]: unrecognized selector sent to instance 0x7fc0baf46f60'

我不明白哪里错了?如果 target 是 self 那么一切正常。

问题出在你的 selector 语法上,它会像这样。

#selector(NotificationView.timerFired(_:))

注意: self 用于当前 ViewController 如果你想为另一个设置动作那么你需要指定 class name.method你的情况是 NotificationView.timerFired.

检查您的错误消息的这一部分:

[_SwiftValue timerFired:]

timerFired: 是选择器的 Objective-C 样式符号。您的 #selector(...) 似乎正常工作。 (虽然不推荐...)

_SwiftValue 是作为选择器目标的对象的 class 名称。这意味着您的目标 target:self.notificationView 已转换为 _SwiftValue.

当您将 notificationView 声明为 Optional 或隐式解包 Optional 时,可能会发生这种情况。如果是这样,试试这个:

Timer.scheduledTimer(timeInterval: 5.0, target: self.notificationView!, selector: #selector(NotificationView.timerFired(_:)), userInfo: nil, repeats: false)

(请不要错过self.notificationView后面的!。)

我尝试了以下代码并触发了 NotificationView.timerFired

class NotificationView {
  @objc func timerFired(_ timer: Timer) {
    print("Timer Fired")
  }
}

class ViewController: UIViewController {
  let notificationView = NotificationView()

  override func viewDidLoad() {
    super.viewDidLoad()

    Timer.scheduledTimer(
      timeInterval: 5.0, 
      target:self.notificationView, 
      selector: #selector(NotificationView.timerFired(_:)), 
      userInfo: nil, 
      repeats: false
    )

  }
}

下面的代码对我有用(在 playground/swift 3 中):

class SomeClass {

    @objc public func timerFired(_ timer: Timer) {
        print("Timer Fired")
    }
}

let s = SomeClass()

Timer.scheduledTimer(timeInterval: 5.0, target:s, selector: #selector(s.timerFired(_:)), userInfo: nil, repeats: false).fire()
//This also will work
//Timer.scheduledTimer(timeInterval: 5.0, target:s, selector: #selector(SomeClass.timerFired(_:)), userInfo: nil, repeats: false).fire()