我如何从 watchOS 2 检查 iPhone 上的应用程序是否打开,并且无论应用程序状态如何都能够发送 NSUserDefaults?

How can i check from watchOS 2 if application on iPhone is opened or not and be able to send NSUserDefaults no matter the app status?

如何从 watchOS 2 检查 iPhone 上的应用程序是否打开?

我想通过 sendMessage 从手表向 iPhone 发送带有 NSUserDefaults 的消息(以便能够在收到消息时更新 phone 上的界面)同时应用程序是 运行,我想发送 NSUserDefaults,即使只有 watchOS 2 应用程序是 运行。

根据我阅读的内容,我发现了这个:

/** The counterpart app must be reachable for a send message to succeed. */
@property (nonatomic, readonly, getter=isReachable) BOOL reachable;

根据我的检查,它始终可以访问。

您可能想要使用 WatchConnectivity 的应用上下文:

看看 WCSession.updateApplicationContext( )

它会在对方可达时立即将最重要的配置信息发送给对方,即使发送时对方不可达。如果多次调用 updateApplicationContext,则只发送最新的。

有关 WatchConnectivity 的更深入信息,请观看 WWDC 2015 session:https://developer.apple.com/videos/wwdc/2015/?id=713

它描述了更多发送数据的方法,但我认为应用程序上下文最适合您。

session 还详细说明了如何确定对方是否可达,但我认为您的用例不需要它。

Reachable 表示 Apple Watch 和 iPhone 通过蓝牙或 wifi 连接。这并不一定意味着 iPhone 应用程序是 运行。如果 reachable 为真,当您尝试从 Apple Watch 发送消息时,它会在后台启动 iPhone 应用程序。您需要尽快分配 WKSession 委托,因为委托方法 (sendMessage) 将很快触发。我想你所说的是如果可以的话调用 sendMessage,而不是使用 transferUserInfo 方法。为此,首先在您的 Apple Watch 上:

func applicationDidFinishLaunching() {
    let session = WCSession.defaultSession()
    session.delegate = self
    session.activateSession()

    // NOTE: This should be your custom message dictionary
    // You don't necessarily call the following code in
    // applicationDidFinishLaunching, but it is here for
    // the simplicity of the example. Call this when you want to send a message.
    let message = [String:AnyObject]()

    // To send your message.
    // You could check reachable here, but it could change between reading the
    // value and sending the message. Instead just try to send the data and if it
    // fails queue it to be sent when the connection is re-established.
    session.sendMessage(message, replyHandler: { (response) -> Void in
        // iOS app got the message successfully
    }, errorHandler: { (error) -> Void in
        // iOS app failed to get message. Send it in the background
        session.transferUserInfo(message)
    })
}

然后,在您的 iOS 应用中:

// Do this here so it is setup as early as possible so
// we don't miss any delegate method calls
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    self.watchKitSetup()  
    return true
}

func watchKitSetup() {
    // Stop if watch connectivity is not supported (such as on iPad)
    if (WCSession.isSupported()) {
        let session = WCSession.defaultSession()
        session.delegate = self
        session.activateSession()
    }
}

func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void) {
    // Handle the message from the apple watch...
    dispatch_async(dispatch_get_main_queue()) {
        // Update UI on the main thread if necessary
    }
}

func session(session: WCSession, didReceiveUserInfo userInfo: [String : AnyObject]) {
    // Handle the message from the apple watch...
    dispatch_async(dispatch_get_main_queue()) {
        // Update UI on the main thread if necessary
    }
}