结合WatchConnectivity和复杂功能 [英] Combining WatchConnectivity and Complications

查看:138
本文介绍了结合WatchConnectivity和复杂功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望我的并发症能够通过Watch Connectivity从iPhone获取数据.我正在使用sendMessage即时消息技术.

I want my complication to get data from the iPhone via Watch Connectivity. I am using sendMessage Instant Messaging technology.

当我尝试获取数据时,我不想打开我的iPhone应用程序,因此这需要在后台进行.

I don't want my iPhone app to be open when I try to get data, so this needs to work in the background.

在iPhone上的ViewController中:

In my ViewController on my iPhone:

import UIKit
import WatchConnectivity

class ViewController: UIViewController, WCSessionDelegate {

var session: WCSession!

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

func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void) {
    if message.count != 1 { return }

    if message["request"] != nil {
        replyHandler(["response" : "data"])
    }
}

在我的ComplicationController中

And in my ComplicationController

var session: WCSession!

func getCurrentTimelineEntryForComplication(complication: CLKComplication, withHandler handler: ((CLKComplicationTimelineEntry?) -> Void)) {
    if complication.family != .ModularSmall {
        handler(nil)
    }

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

    var respondedString = "not"

    session.sendMessage(["request" : ""], replyHandler: {
        (resp) -> Void in
        respondedString = resp["response"]
    }, errorHandler: nil)

    let circularTemplate = CLKComplicationTemplateModularSmallSimpleText()
    circularTemplate.textProvider = CLKSimpleTextProvider(text: respondedString)
    let timelineEntry = CLKComplicationTimelineEntry(date: NSDate(), complicationTemplate: circularTemplate)
    handler(timelineEntry)
}

我在手表上唯一看到的是不是".为什么并发症不显示接收到的数据?

The only thing I can see on my Watch is "not". Why doesn't the complication show the received data?

推荐答案

主要问题是您正在尝试在并发症控制器中进行异步调用.

The main issue is that you're trying to make an asynchronous call within your complication controller.

sendMessage:调用之后的代码将在 之前执行,甚至在您的回复处理程序得到响应之前.这就是为什么在您收到答复之前,并发症已经显示为"not",因为已设置了模板的文本.

The code following your sendMessage: call will be executed before your reply handler has even gotten a response. This is why your complication shows "not" as the template's text has been set, before you have received a reply.

有时,在getCurrentTimelineEntryForComplication返回之后,sendMessage将收到响应并调用应答处理程序,该处理程序只会设置respondedString,然后退出该块.

Sometime later, after getCurrentTimelineEntryForComplication has returned, sendMessage will receive a response and call the reply hander, which will merely set respondedString, then exit that block.

应避免的操作:

您应该考虑

You should consider Apple's recommendations, and not try to fetch any data within the complication controller.

数据源类的工作是尽快向ClockKit提供任何请求的数据.数据源方法的实现应尽量少.请勿使用数据源方法从网络中获取数据,计算值或执行任何可能会延迟该数据传递的操作.如果您需要获取或计算并发症数据,请在iOS应用或WatchKit扩展的其他部分进行处理,然后将数据缓存在并发症数据源可以访问的位置.数据源方法唯一要做的就是获取缓存的数据,并将其设置为ClockKit要求的格式.

The job of your data source class is to provide ClockKit with any requested data as quickly as possible. The implementations of your data source methods should be minimal. Do not use your data source methods to fetch data from the network, compute values, or do anything that might delay the delivery of that data. If you need to fetch or compute the data for your complication, do it in your iOS app or in other parts of your WatchKit extension, and cache the data in a place where your complication data source can access it. The only thing your data source methods should do is take the cached data and put it into the format that ClockKit requires.

此外,您在数据源中执行的任何活动都将不必要地消耗分配给并发症的每日执行时间预算.

Also, any activity you perform within your data source will needlessly use up the daily execution time budget that is allotted to your complication.

如何为并发症提供数据?

Apple提供了Watch Connectivity transferCurrentComplicationUserInfo方法,该方法将立即从手机中传输并发症信息(的词典)观看.

Apple provides a Watch Connectivity transferCurrentComplicationUserInfo method which will immediately transfer (a dictionary of) complication info from the phone to the watch.

当您的iOS应用收到用于并发症的更新数据时,可以使用Watch Connectivity框架立即更新并发症. WCSession的transferCurrentComplicationUserInfo:方法将高优先级消息发送到您的WatchKit扩展,并根据需要唤醒以传递数据.接收到数据后,根据需要扩展或重新加载时间轴,以强制ClockKit从数据源中请求新数据.

When your iOS app receives updated data intended for your complication, it can use the Watch Connectivity framework to update your complication right away. The transferCurrentComplicationUserInfo: method of WCSession sends a high priority message to your WatchKit extension, waking it up as needed to deliver the data. Upon receiving the data, extend or reload your timeline as needed to force ClockKit to request the new data from your data source.

在表侧,您拥有WCSessionDelegate手柄didReceiveUserInfo,并使用收到的数据更新并发症:

On the watch side, you have your WCSessionDelegate handle didReceiveUserInfo and use the data you received to update your complication:

func session(session: WCSession, didReceiveUserInfo userInfo: [String : AnyObject]) {
    if let ... { // Retrieve values from dictionary

        // Update complication
        let complicationServer = CLKComplicationServer.sharedInstance()
        guard let activeComplications = complicationServer.activeComplications else { // watchOS 2.2
            return
        }

        for complication in activeComplications {
            complicationServer.reloadTimelineForComplication(complication)
        }
    }
}

Apple工程师通常建议设置一个数据管理器来保存数据.在并发症控制器中,您将从数据管理器中检索最新信息以用于时间轴.

Apple engineers generally recommend setting up a data manager to hold the data. In your complication controller, you would retrieve the latest information from the data manager to use for your timeline.

GitHub上已有几个使用这种方法的项目.

There are several existing projects on GitHub which use this approach.

如果您仍然希望从手表端请求数据:

您想将WCSession代码从复杂控制器中移出,进入watch扩展名,并作为WKExtension init的一部分进行激活.

You'd want to move your WCSession code out of the complication controller, into the watch extension, and activate it as part of the WKExtension init.

关键是一旦收到数据,让回复处理程序手动更新并发症.

The key is to have the reply handler manually update the complication once the data is received.

调用会话代表的回复处理程序时,可以使用我之前提供的更新并发症代码来重新加载并发症的时间轴.

When your session delegate's reply handler is called, you can use the update complication code I supplied earlier to reload your complication's timeline.

如果您使用计划的并发症更新来触发此更新,则该特定方法的缺点是您将执行两次更新.第一次更新将启动对数据的请求,但没有任何新数据可使用.第二次(手动)更新发生在接收到数据之后,此时新数据将出现在时间轴上.

这就是为什么通过电话在后台提供数据的方法效果更好的原因,因为它只需要更新一次即可.

这篇关于结合WatchConnectivity和复杂功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆