我有一个带有按钮的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发送消息时发生的情况)
答案 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应用程序),向我展示了如何解决这个问题!