1

我有一个带有按钮的 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)
        }
    }
}

即使我看到成功回复到手表,有时本地通知实际上并没有被取消。

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

4

1 回答 1

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
        }
    }
}

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

于 2016-06-08T16:13:42.033 回答