Timer.scheduledTimer 抛出 "unrecognized selector sent to instance"

Timer.scheduledTimer throws "unrecognized selector sent to instance"

我正在安排一个定时器来推送通知。需要注意的是,我的#selector 是下面代码中概述的单例函数。但是,当计时器发出信号并调用 #selector(NotificationManager.instance.pushNotification(timer:)) 时,我得到下面概述的异常转储。当我采用相同的功能并将其放置在视图控制器中时,世界上一切正常,没有问题。有什么想法吗?

2017-12-09 20:33:47.439754-0500 Accumoo[3404:2488862] -[MyApp.MainViewController pushNotificationWithTimer:]: unrecognized selector sent to instance 0x107077800
2017-12-09 20:33:47.440181-0500 Accumoo[3404:2488862] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[MyApp.MainViewController pushNotificationWithTimer:]: unrecognized selector sent to instance 0x107077800'
*** First throw call stack:
(0x184c89d04 0x183ed8528 0x184c971c8 0x18e47f110 0x184c8f6b0 0x184b7501c 0x18567bd24 0x184c3292c 0x184c32650 0x184c31e50 0x184c2fa38 0x184b4ffb8 0x1869e7f84 0x18e1242e8 0x104b3f624 0x18467256c)
libc++abi.dylib: terminating with uncaught exception of type NSException 

这是代码...

在我的视图控制器中...

// Send user a local notification if they have the app running in the background...
let userInfo = ["title" : "Title", "body" : "Body", "timeIntervalSeconds" : Double(0), "repeats" : false] as [String : Any]
Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(NotificationManager.instance.pushNotification(timer:)), userInfo: userInfo, repeats: false)

在我的 NotificationManager Class...

class NotificationManager /*: PushNotificationProtocol*/ {
   static let instance = NotificationManager()

   private init() {
   }

   @objc public func pushNotification(timer:Timer) {
      guard let userInfo = timer.userInfo as? Dictionary<String, Any> else { return }

      let title = (userInfo["title"] as? String).valueOrDefault()
      let body = (userInfo["body"] as? String).valueOrDefault()
      let timeIntervalSeconds = (userInfo["timeIntervalSeconds"] as? Double) ?? 0
      let repeats = (userInfo["repeats"] as? Bool) ?? false

      self.pushNotification(sender: nil, title: title, body: body, timeIntervalSeconds: timeIntervalSeconds, repeats: repeats)
   }

   public func pushNotification(sender:Any?, title:String, body:String) {
      self.pushNotification(sender: sender, title: title, body: body, timeIntervalSeconds: 0, repeats: false)
   }

   public func pushNotification(sender:Any?, title:String, body:String, timeIntervalSeconds:Double, repeats:Bool) {
      // Center
      let center = UNUserNotificationCenter.current()

      // Content...
      let content = UNMutableNotificationContent()
      content.title = title
      content.body = body
      content.sound = UNNotificationSound.default()

      // Trigger
      let trigger = UNTimeIntervalNotificationTrigger(timeInterval: timeIntervalSeconds, repeats: repeats)

      // Push it...
      // Does this need to be unique?
      let identifier = "NotificationManagerIdentification"
      let request = UNNotificationRequest(identifier: identifier, content: content, trigger: trigger)
      center.add(request, withCompletionHandler: { (error) in
         if let error = error {
            print("Something went wrong: \(error)")
         }
      })
   }
}

** * 更新 * **

原来对 Timer.scheduleTimer 的调用需要这样编码(参见@maddy 的回答):

// Send user a local notification if they have the app running in the background...
let userInfo = ["title" : "Title", "body" : "Body", "timeIntervalSeconds" : Double(10), "repeats" : false] as [String : Any]
Timer.scheduledTimer(timeInterval: 0.5, target: NotificationManager.instance, selector: #selector(NotificationManager.instance.pushNotification(timer:)), userInfo: userInfo, repeats: false)

您向计时器传递了错误的目标。

变化:

Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(NotificationManager.instance.pushNotification(timer:)), userInfo: userInfo, repeats: false)

至:

Timer.scheduledTimer(timeInterval: 0.5, target: NotificationManager.instance, selector: #selector(NotificationManager.instance.pushNotification(timer:)), userInfo: userInfo, repeats: false)

请记住,目标需要 class 的一个实际实现选择器的实例来指定。您传递的是视图控制器 self