【问题标题】:How to call a method defined on the iPhone from the Apple Watch如何从 Apple Watch 调用 iPhone 上定义的方法
【发布时间】:2015-01-03 09:26:39
【问题描述】:

有没有什么方法可以从 Watchkit 扩展调用 iPhone 上类中定义的方法?

据我了解,目前Watch kit和iPhone之间本地通信的一种方式是使用NSUserDefaults,但还有其他方式吗?

一个简单的例子会很棒。

【问题讨论】:

    标签: ios objective-c swift watchkit apple-watch


    【解决方案1】:

    您可以将类添加到两个目标(主 iOS 应用程序和 WatchKit 扩展)并直接使用 WatchKit 扩展中的方法。

    方便地添加依赖很少的类(首选实用程序或类别)。 如果文件已经添加到项目中,您可以将其删除(删除引用)并再次添加它并包含多个目标。

    比如我在项目中的分类NSString+color在iOS app和Watch App中都能正常工作。

    更新:您也可以在右侧面板(实用程序)中执行此操作。见下方链接:cs621620.vk.me/v621620973/13f86/9XYDH1HL5BI.jpg

    【讨论】:

    • 你是怎么做到的?尽管我已经为 WatchKit 应用程序创建了一个目标,但我看不到可以添加到多个目标的选项。
    • 在您将文件添加到项目后,是否可以对文件执行此操作?我知道您可以删除引用并再次添加文件,然后将显示此对话框,但是我正在寻找一种更快捷的方法。
    • 你也可以在右侧面板(实用工具)cs621620.vk.me/v621620973/13f86/9XYDH1HL5BI.jpg
    • 嘿,我在我的项目中做了同样的事情,但是我的手表应用程序编译了这个类和其他一些类,我还没有添加到 watch Extension Target 并因此而出错。可能是什么问题?
    • 这适用于某些类。但是,我对任何链接到 SystemConfiguration/SystemConfiguration 框架的类都有疑问。有什么想法吗?
    【解决方案2】:

    根据您要完成的任务,您的 WatchKit 扩展程序和 iOS 应用程序之间有两种主要的“通信”方式。

    1. openParentApplication:回复:
    这将在后台打开您的 iOS 应用程序,并允许您从 iOS 代码执行逻辑并将响应发送回您的扩展程序。例如 -

        [InterfaceController openParentApplication:@{ @"command": @"foo" }
                                             reply:^(NSDictionary *replyInfo, NSError *error) {
                                             self.item = replyInfo[@"bar"];
        }];
    

    查看框架参考 -https://developer.apple.com/library/prerelease/ios/documentation/WatchKit/Reference/WKInterfaceController_class/index.html#//apple_ref/occ/clm/WKInterfaceController/openParentApplication:reply:

    MMWormhole 是一个可用于管理这些通信的库

    2。共享容器
    如果您只需要访问您的 iOS 应用程序可以访问的相同数据,您可以跨两个目标实现共享容器。

    这可能从仅使用访问共享的 NSUserDefaults(如您所提到的)或一直到使用 Core Data 和访问跨 iOS 和 WatchKit 的共享持久性堆栈。

    编程参考 - https://developer.apple.com/library/ios/technotes/tn2408/_index.html

    3.单身人士
    也许您只需要从 WatchKit 扩展访问共享逻辑,而不需要上述两个选项的复杂性。只要您不在两个目标之间保留任何数据,您就可以创建一个单例类,您可以从扩展中调用该类来执行您需要的方法。

    【讨论】:

    • 为什么不能只调用实例方法?
    【解决方案3】:

    根据Apple的WatchKit Programming Guide,您可以使用openParentApplication与iPhone上的iOS应用程序进行通信并传递字典。父应用程序通过其AppDelegate 中的handleWatchKitExtensionsRequest 处理此调用。从那里您可以根据传递的参数调用其他方法。

    handleWatchKitExtensionRequest 然后调用reply 方法将参数传回WatchKit Extension:

    Watchkit 扩展:

    // Call the parent application from Apple Watch
    
    // values to pass
    let parentValues = [
        "value1" : "Test 1",
        "value2" : "Test 2"
    ]
    
    WKInterfaceController.openParentApplication(parentValues, reply: { (replyValues, error) -> Void in
        println(replyValues["retVal1"])
        println(replyValues["retVal2"])
    })
    

    iOS 应用:

    // in AppDelegate.swift
    func application(application: UIApplication!, handleWatchKitExtensionRequest userInfo: [NSObject : AnyObject]!, reply: (([NSObject : AnyObject]!) -> Void)!) {
        // retrieved parameters from Apple Watch
        println(userInfo["value1"])
        println(userInfo["value2"])
    
        // pass back values to Apple Watch
        var retValues = Dictionary<String,String>()
    
        retValues["retVal1"] = "return Test 1"
        retValues["retVal2"] = "return Test 2"
    
        reply(retValues)
    }
    

    请注意,这似乎在 Xcode 6.2 Beta 3 中被破坏了。

    【讨论】:

    • “请注意,目前这似乎在 Xcode 6.2 Beta 3 中被破坏了。”——根据我的经验,虽然我使用的是 Objective C 代码,但这可能会有所不同。
    • 为什么不能只调用实例方法?
    • 对我来说它似乎也被打破了。我正在尝试使手表套件扩展与 Objective C 应用程序进行通信。
    【解决方案4】:

    对于 WatchOS2,openParentApplication 已弃用。它的替换是WCSession in Watch Connectivity Framework

    首先,在watch(ExtensionDelegate)和iOS(AppDelegate)中使用以下代码初始化WCSession

    if WCSession.isSupported() {
      let session = WCSession.defaultSession()
      session.delegate = self
      session.activateSession()
    }
    

    使用

    将通知从手表发送到手机
    session.sendMessage(msg, replyHandler: { (responses) -> Void in
      print(responses)
     }) { (err) -> Void in
     print(err)
    }
    

    使用AppDelegate处理消息

    func session(_ session: WCSession,
                 didReceiveMessage message: [String : AnyObject],
                 replyHandler replyHandler: ([String : AnyObject]) -> Void)     
    {
       //do something according to the message dictionary
       responseMessage = ["key" : "value"] //values for the replyHandler
       replyHandler(responseMessage)
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-08-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多