如何从watchOS 2唤醒iPhone应用程序?

Ben*_*Ben 13 ios apple-watch

我有一个具有非常丰富的网络层的应用程序,我的Apple Watch应用程序取决于所有型号.不幸的是,该应用程序不够模块化,无法在手表应用程序中使用此图层.

我通过使用openParentApplication解决了这个问题:唤醒iPhone应用程序,执行请求并返回结果.

在watchOS 2中,这种方法已经消失,我应该使用WatchConnectivity.使用它的最佳方法是发送userInfo字典.

但是,如何唤醒iPhone应用程序来处理我的请求?要获得有关新userInfos的通知,我必须使用WCSessionDelegate,为此我需要一个WCSession对象.但是什么时候应该创造呢?以及如何唤醒应用程序?

Ben*_*Ben 15

我问了一位Apple工程师,并得到了以下提示:iOS-App应该在后台任务中启动.所以以下内容对我很有用:

UIApplication *application = [UIApplication sharedApplication];

__block UIBackgroundTaskIdentifier identifier = UIBackgroundTaskInvalid;
dispatch_block_t endBlock = ^ {
    if (identifier != UIBackgroundTaskInvalid) {
        [application endBackgroundTask:identifier];
    }
    identifier = UIBackgroundTaskInvalid;
};

identifier = [application beginBackgroundTaskWithExpirationHandler:endBlock];
Run Code Online (Sandbox Code Playgroud)

将此添加到您的session:didReceiveMessage:session:didReceiveMessageData:方法以启动三分钟超时的后台任务.


Jus*_*itz 6

快速版Benjamin Herzog的建议如下.值得注意的是,虽然我确实选择将Watch启动的工作推送到后台任务,但只要我的应用程序在后台,系统就可以将其唤醒.在后台任务中完成工作似乎不是必需的,但这是最佳实践.

override init() {
    super.init()
    if WCSession.isSupported() {
        session = WCSession.defaultSession()
        session.delegate = self
        session.activateSession()
    }
}

func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void) {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
        let taskID = self.beginBackgroundUpdateTask()
        //Do work here...
        self.endBackgroundUpdateTask(taskID)
    })
    var replyValues = Dictionary<String, AnyObject>()
    let status = "\(NSDate()): iPhone message: App received and processed a message: \(message)."
    print(status)
    replyValues["status"] = status
    replyHandler(replyValues)
}

func beginBackgroundUpdateTask() -> UIBackgroundTaskIdentifier {
    return UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler({})
}

func endBackgroundUpdateTask(taskID: UIBackgroundTaskIdentifier) {
    UIApplication.sharedApplication().endBackgroundTask(taskID)
}
Run Code Online (Sandbox Code Playgroud)


ccj*_*sen 5

在 WatchKit 扩展中,您将需要使用 WatchConnectivity WCSession sendMessage API。在扩展中检查 iOS 应用程序是否可访问,然后发送消息:

let session = WCSession.defaultSession();
if session.reachable {
    let message = ["foo":"bar"]
    session.sendMessage(message, replyHandler: nil, errorHandler: { (error) -> Void in
        print("send failed with error \(error)")
    })
}
Run Code Online (Sandbox Code Playgroud)

此消息将导致系统在后台唤醒 iOS 应用程序,因此请确保在后台运行时调用的一段 iOS 应用程序代码中设置 WCSession(例如:您不想将其放入 UIViewController 的子类的 viewDidLoad 中)以便接收消息。由于您将请求一些信息,因此您可能希望利用回复块。

这就是在后台启动 iOS 应用程序的方法,尽管 WatchConnectivity WWDC 会议建议尽可能使用“后台”传输方法。如果您的手表应用程序是只读的,那么您应该能够使用后台传输对 iOS 设备上的任何更改进行排队,然后它们将在下次运行时传送到手表应用程序。