当iPhone从配对的Apple Watch接收消息时,本地通知不会被取消(有时)

时间:2016-06-05 16:27:44

标签: ios watchkit apple-watch appdelegate watchconnectivity

我有一个带有按钮的Apple Watch应用程序,可以点按该按钮来记录事件。记录事件时,我想取消应用中的所有待处理本地通知。问题是有时本地通知被取消,而其他时候则没有。

以下是Watch应用程序的代码。点击按钮后,我会向iPhone应用程序发送消息:

func buttonTapped() {

    // check to make sure the session is reachable, so a message can be sent
    if session.reachable == true {

        // a dict containing the date of the event to be sent to the iPhone
        let dict = ["date" : NSDate()]

        // send the dict and specify the replyHandler
        session.sendMessage(dict, replyHandler: { (reply) in

                if reply["success"] as? Bool == true {

                    print("notifications were cancelled")
                }

            }, errorHandler: { (error) in

                // some kind of error has occurred
            }
        )
    }
}

在iPhone上的AppDelegate中,我实现了WatchConnectivity委托方法来接收消息,这是通知被清除的地方。然后,调用replyHandler向Watch应用程序指示消息已成功接收并处理:

func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void) {

    if message["date"] != nil {

        dispatch_async(dispatch_get_main_queue()){

            let reply = ["success" : true]

            UIApplication.sharedApplication().cancelAllLocalNotifications()

            // send the reply to the Watch to confirm all this has happened
            replyHandler(reply)
        }
    }
}

即使我看到成功的回复回到了Watch,本地通知有时也没有被取消。

这似乎是iOS或watchOS错误,而不是我可以解决的问题?当应用程序在后台启动时,可能无法保证可以访问某些API? (这似乎是使用WatchConnectivity发送消息时发生的情况)

1 个答案:

答案 0 :(得分:1)

当以这种方式在AppDelegate中收到消息时,应用程序将在后台启动(即使它没有显示在多任务处理屏幕中)。但由于我没有明确要求iOS提供后台时间,因此我didReceiveMessage中的代码并未始终完全执行。

解决方案是专门询问背景时间。以下是我如何更改didReceiveMessage以使其正常工作:

// initialize a background task identifier
var backgroundTask: UIBackgroundTaskIdentifier = UIBackgroundTaskInvalid

func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void) {

    if message["date"] != nil {

        dispatch_async(dispatch_get_main_queue()){

            // begin the background task
            self.backgroundTask = UIApplication.sharedApplication().beginBackgroundTaskWithName("CancelNotifications", expirationHandler: {

                // this expirationHandler will be called to end and invalidate the background task in case it doesn't have enough time to complete

                UIApplication.sharedApplication().endBackgroundTask(self.backgroundTask)
                self.backgroundTask = UIBackgroundTaskInvalid
            })

            let reply = ["success" : true]

            UIApplication.sharedApplication().cancelAllLocalNotifications()

            // send the reply to the Watch to confirm all this has happened
            replyHandler(reply)

            // let iOS know the background task is done
            UIApplication.sharedApplication().endBackgroundTask(self.backgroundTask)
            self.backgroundTask = UIBackgroundTaskInvalid
        }
    }
}

非常感谢David Walsh,creator of HeartWatch(一款非常棒的Apple Watch和iPhone应用程序),向我展示了如何解决这个问题!