更新 Apple Watch 复杂功能数据的流程是什么? [英] What is the flow for updating complication data for Apple Watch?

查看:65
本文介绍了更新 Apple Watch 复杂功能数据的流程是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在学习互联网上的大量教程,以了解如何设置复杂功能.我按预期设置复杂功能没有问题.

直到初始时间线条目过期.12 小时后,我不知道如何更新它以保持复杂功能.我将在下面分享我所拥有的一切,希望有人可以帮助我填写.

在这里,我为要在复杂功能上显示的数据创建了变量.

结构数据 = {变量名:字符串var startString: 字符串变量开始日期:NSDate}

以下数组是此数据的容器.

var dataArray = [数据]

这允许在手表锁定时显示复杂功能.

func getPrivacyBehaviorForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationPrivacyBehavior) -> Void) {处理程序(.ShowOnLockScreen)}

这允许在并发症上进行向前的时间旅行.

func getSupportedTimeTravelDirectionsForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationTimeTravelDirections) -> Void) {处理程序([.Forward])}

这里,我将时间线的开始时间设置为等于现在.

func getTimelineStartDateForComplication(complication: CLKComplication, withHandler handler: (NSDate?) -> Void) {处理程序(NSDate())}

这里,我将时间线的结束时间设置为从现在开始的 12 小时.

func getTimelineEndDateForComplication(complication: CLKComplication, withHandler handler: (NSDate?) -> Void) {处理程序(NSDate(timeIntervalSinceNow:(60 * 60 * 12)))}

在这里,我创建了复杂功能的模板.这是为了在用户在手表上浏览所有复杂功能时看到我的复杂功能时向他们显示示例数据.

func getPlaceholderTemplateForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationTemplate?) -> Void) {让 headerTextProvider = CLKSimpleTextProvider(text: "Some Data")让 body1TextProvider = CLKSimpleTextProvider(text: "Some Data Time")让模板 = CLKComplicationTemplateModularLargeStandardBody()template.headerTextProvider = headerTextProvidertemplate.body1TextProvider = body1TextProvider处理程序(模板)}

这将创建复杂功能的第一个时间线条目.一旦启用复杂功能,就会运行此代码并立即相应地填充复杂功能.

func getCurrentTimelineEntryForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationTimelineEntry?) -> Void) {创建数据()如果complication.family == .ModularLarge {如果 dataArray.count != 0 {让 firstData = dataArray[0]让 headerTextProvider = CLKSimpleTextProvider(text: firstData.name)让 body1TextProvider = CLKSimpleTextProvider(text: firstData.startString)让模板 = CLKComplicationTemplateModularLargeStandardBody()template.headerTextProvider = headerTextProvidertemplate.body1TextProvider = body1TextProvider让时间线条目 = CLKComplicationTimelineEntry(日期:NSDate(),complicationTemplate:模板)处理程序(时间线条目)} 别的 {让 headerTextProvider = CLKSimpleTextProvider(文本:无数据")让 body1TextProvider = CLKSimpleTextProvider(文本:创建一些数据")让模板 = CLKComplicationTemplateModularLargeStandardBody()template.headerTextProvider = headerTextProvidertemplate.body1TextProvider = body1TextProvider让时间线条目 = CLKComplicationTimelineEntry(日期:NSDate(),complicationTemplate:模板)处理程序(时间线条目)}} 别的 {处理程序(无)}}

这是我为我目前拥有的所有数据创建时间线条目的地方.

func getTimelineEntriesForComplication(complication: CLKComplication, afterDate date: NSDate, limit: Int, withHandler handler: ([CLKComplicationTimelineEntry]?) -> Void) {创建数据()var 条目 = [CLKComplicationTimelineEntry]()对于 dataArray 中的 dataObject {如果条目数<限制&&data.startDate.timeIntervalSinceDate(date) >0 {让 headerTextProvider = CLKSimpleTextProvider(text: dataObject.name)让 body1TextProvider = CLKSimpleTextProvider(text: dataObject.startString)让模板 = CLKComplicationTemplateModularLargeStandardBody()template.headerTextProvider = headerTextProvidertemplate.body1TextProvider = body1TextProvider让时间线条目 = CLKComplicationTimelineEntry(date: NSDate(timeInterval: (-10*60), sinceDate: data.startDate), complicationTemplate: 模板)entry.append(timelineEntry)}}处理程序(条目)}

这会告诉手表何时更新并发症数据.

func getNextRequestedUpdateDateWithHandler(handler: (NSDate?) -> Void) {处理程序(NSDate(timeIntervalSinceNow: 60 * 60 * 6))}

这是我遇到问题的地方.

如何创建新数据并重新加载时间线?什么是流量?我不是要延长时间线,而是要完全替换它.我完全不知所措.Apple 的文档在这一点上非常含糊.我知道我需要实现以下方法,但我不知道如何实现.有人可以帮我填写这个代码吗?

func requestsUpdateDidBegin() {createData()//我假设 createData() 在这里?如果是这样,我如何根据结果填充新的时间线条目?}func 请求UpdateBudgetExhausted() {//这不可能是这种情况,因为我还没有让它工作一次.}func reloadTimelineForComplication(complication: CLKComplication!) {//这个方法似乎什么都不做.}

更新:

多亏了 El Tea,我让它工作了.我需要将 CLKComplicationServer 的实例添加到 requestsUpdateDidBegin 并将 reloadTimeline 方法放入其中.

这是更新的代码:

func requestsUpdateDidBegin() {print("并发症更新开始")创建数据()让 server=CLKComplicationServer.sharedInstance()用于补偿(server.activeComplications){server.reloadTimelineForComplication(comp)print("时间轴已重新加载!")}}func 请求UpdateBudgetExhausted() {print("预算已用完")}

解决方案

复杂功能刷新的流程按时间间隔完成,遵循以下顺序:

  • iOS 调用您的函数 requestedUpdateDidBegin()requestedUpdateBudgetExhausted()(如果您的预算用完,您什么都不做将导致更新,直到您获得更多执行时间.)
  • requestedUpdateDidBegin() 内部 必须调用 reloadTimelineForComplication()extendTimelineForComplication() 来指定哪个您想要重新加载或添加数据的并发症.如果你不这样做,什么都不会发生!
  • 根据您调用的是 reload 还是 extend,iOS 会调用 getCurrentTimelineEntryForComplication()getTimelineEntriesForComplication() 之一或两者)
  • 无论您是否更新了复杂功能,iOS 都会调用 getNextRequestedUpdateDateWithHandler() 来确定您下次希望重复上述步骤的时间.

注意:最后两个步骤不一定要按这个顺序发生.

该过程以这种方式工作,因此 iOS 不会要求您反复重新生成相同的数据.它让您有机会在 requestedUpdateDidBegin() 中决定是否需要更新您的复杂功能.如果没有,您的代码应该返回.(这会减少您的复杂功能的执行时间,并有助于避免 iOS 因使用了每日预算而中断您的应用程序的进一步更新).但是如果你有新数据,你需要通过调用 reloadTimelineForComplication()extendTimelineForComplication()

告诉 iOS

据我所知,除了您没有在 requestedUpdateDidBegin() 中请求重新加载或扩展之外,您在那里编写的所有内容看起来都不错.您的复杂功能可能会在多个位置出现在表盘上,并且不同的模板具有不同的显示行为,因此您必须使所有这些都无效.这是我的代码的样子:

func requestsUpdateDidBegin() {//未显示:决定您是否真的需要更新您的复杂功能.//如果你这样做,执行以下代码:让 server=CLKComplicationServer.sharedInstance()用于补偿(server.activeComplications){server.reloadTimelineForComplication(comp)}}

请注意,除了时间间隔之外,还有其他方法可以启动刷新,包括推送警报、在手表应用程序运行时执行重新加载,或使用带有 WCSession 的 Watch Connectivity 框架让您的手机应用程序发送更新数据以通过以下方式立即显示transferCurrentComplicationUserInfo().有关详细信息,请参阅 Apple 文档中的更新并发症数据.>

我在模拟器测试中取得了成功,更新间隔短至 10 分钟.由于执行时间预算,您可能不应该在真正的手表上频繁更新,但这将使您无需等待 12 小时即可测试代码.

I've been following a lot of tutorials on the internet to learn how to set up the complication. I have no problem getting the complication set up as expected.

Until the initial timeline entries expire. After 12 hours, I do not know how to update it to keep the complication live. I'll share everything I have below and hopefully somebody can help fill me in.

Here, I create the variables for my data that I want to display on the complication.

struct data = {
var name: String
var startString: String
var startDate: NSDate
}

The following array is a container for this data.

var dataArray = [data]

This allows the complication to be shown when the watch is locked.

func getPrivacyBehaviorForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationPrivacyBehavior) -> Void) {
    handler(.ShowOnLockScreen)
}

This allows forward Time Travel on the complication.

func getSupportedTimeTravelDirectionsForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationTimeTravelDirections) -> Void) {
    handler([.Forward])
}

Here, I set the starting time of the timeline to be equal to now.

func getTimelineStartDateForComplication(complication: CLKComplication, withHandler handler: (NSDate?) -> Void) {
    handler(NSDate())
}

Here, I set the ending time of the timeline to be equal to 12 hours from now.

func getTimelineEndDateForComplication(complication: CLKComplication, withHandler handler: (NSDate?) -> Void) {
    handler(NSDate(timeIntervalSinceNow: (60 * 60 * 12)))
}

Here, I create the template of the complication. This is to show sample data for users when they see my complication while browsing all complications on their watch.

func getPlaceholderTemplateForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationTemplate?) -> Void) {

    let headerTextProvider = CLKSimpleTextProvider(text: "Some Data")
    let body1TextProvider = CLKSimpleTextProvider(text: "Some Data Time")
    let template = CLKComplicationTemplateModularLargeStandardBody()
    template.headerTextProvider = headerTextProvider
    template.body1TextProvider = body1TextProvider

    handler(template)
}

This creates the very first timeline entry for the complication. As soon as the complication is enabled, this code will be run and immediately populate the complication accordingly.

func getCurrentTimelineEntryForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationTimelineEntry?) -> Void) {

    createData()

    if complication.family == .ModularLarge {

        if dataArray.count != 0 {

            let firstData = dataArray[0]
            let headerTextProvider = CLKSimpleTextProvider(text: firstData.name)
            let body1TextProvider = CLKSimpleTextProvider(text: firstData.startString)
            let template = CLKComplicationTemplateModularLargeStandardBody()
            template.headerTextProvider = headerTextProvider
            template.body1TextProvider = body1TextProvider
            let timelineEntry = CLKComplicationTimelineEntry(date: NSDate(), complicationTemplate: template)
            handler(timelineEntry)
        } else {
            let headerTextProvider = CLKSimpleTextProvider(text: "No Data")
            let body1TextProvider = CLKSimpleTextProvider(text: "Create some data")
            let template = CLKComplicationTemplateModularLargeStandardBody()
            template.headerTextProvider = headerTextProvider
            template.body1TextProvider = body1TextProvider

            let timelineEntry = CLKComplicationTimelineEntry(date: NSDate(), complicationTemplate: template)
            handler(timelineEntry)
        }

    } else {
        handler(nil)
    }

}

This is where I create timeline entries for all of the data that I currently have.

func getTimelineEntriesForComplication(complication: CLKComplication, afterDate date: NSDate, limit: Int, withHandler handler: ([CLKComplicationTimelineEntry]?) -> Void) {

    createData()

    var entries = [CLKComplicationTimelineEntry]()

    for dataObject in dataArray {

        if entries.count < limit && data.startDate.timeIntervalSinceDate(date) > 0 {

            let headerTextProvider = CLKSimpleTextProvider(text: dataObject.name)
            let body1TextProvider = CLKSimpleTextProvider(text: dataObject.startString)
            let template = CLKComplicationTemplateModularLargeStandardBody()
            template.headerTextProvider = headerTextProvider
            template.body1TextProvider = body1TextProvider
            let timelineEntry = CLKComplicationTimelineEntry(date: NSDate(timeInterval: (-10*60), sinceDate: data.startDate), complicationTemplate: template)
            entries.append(timelineEntry)

        }

    }

    handler(entries)

}

This tells the watch when to update the complication data.

func getNextRequestedUpdateDateWithHandler(handler: (NSDate?) -> Void) {
    handler(NSDate(timeIntervalSinceNow: 60 * 60 * 6))
}

This is where I'm running into problems.

How do I create my new data and reload the timeline? What is the flow? I'm not trying to extend the timeline, but rather to completely replace it. I'm at a complete loss. Apple's docs are pretty vague when it comes to this point. I know that I need to implement the following methods, but I don't know how. Can somebody help me to fill in this code?

func requestedUpdateDidBegin() {
    createData() //I assume createData() goes here? If so, how do I populate the new timeline entries based on the results?
}

func requestedUpdateBudgetExhausted() {
    //This can't possibly be the case as I haven't gotten it to work once.
}

func reloadTimelineForComplication(complication: CLKComplication!) {
      //This method appears to do nothing.
}

Update:

Thanks to El Tea, I've got it working. I need to add an instance of CLKComplicationServer to requestedUpdateDidBegin and put the reloadTimeline method inside.

Here is the updated code:

func requestedUpdateDidBegin() {
    print("Complication update is starting")

    createData()

    let server=CLKComplicationServer.sharedInstance()

    for comp in (server.activeComplications) {
        server.reloadTimelineForComplication(comp)
        print("Timeline has been reloaded!")
    }

}

func requestedUpdateBudgetExhausted() {
    print("Budget exhausted")
}

解决方案

The flow for a complication refresh that is being done on a time interval follows this sequence:

  • iOS calls your function requestedUpdateDidBegin() or requestedUpdateBudgetExhausted() (If your budget is exhausted nothing you do will cause an update until you're given more execution time.)
  • Inside of requestedUpdateDidBegin() you have to call reloadTimelineForComplication() or extendTimelineForComplication() to specify which of your complications you want reloaded or to have data added to. If you don't do this, nothing happens!
  • Depending on if you called reload or extend, iOS makes calls to one or both of getCurrentTimelineEntryForComplication() and getTimelineEntriesForComplication()
  • Irrespective of whether or not you updated your complication, iOS calls getNextRequestedUpdateDateWithHandler() to find out when you next want the above steps to repeat.

Note: the last two steps don't necessarily have to happen in that order.

The process works this way so that iOS doesn't ask you to repeatedly regenerate the same data. It gives you a chance in requestedUpdateDidBegin() to decide if your complication needs updating. If it doesn't, your code should just return. (This reduces your complication's execution time and helps avoid iOS from cutting off your app from further updates for having used its daily budget). But if you do have new data, you need to tell iOS by calling reloadTimelineForComplication() or extendTimelineForComplication()

From what I can tell, everything you've written there looks good other than you weren't requesting a reload or extend inside requestedUpdateDidBegin(). It's possible for your complication to be visible on the watch face in more than one position, and for different templates to have different display behaviours, so you have to invalidate all of them. Here is what my code looks like:

func requestedUpdateDidBegin() {

    //Not shown: decide if you actually need to update your complication.
    //If you do, execute the following code:

    let server=CLKComplicationServer.sharedInstance()

    for comp in (server.activeComplications) {
        server.reloadTimelineForComplication(comp)
    }
}

Note that besides time intervals that there are other ways to initiate refreshes including push alerts, executing reloads when your watch app runs, or using the Watch Connectivity framework with a WCSession to have your phone app send update data to be displayed immediately via transferCurrentComplicationUserInfo(). See Updating Your Complication Data in Apple's docs for more info.

I've had success in the simulator testing update intervals as short as ten minutes. You probably shouldn't update that frequently on the real watch due to the execution time budget, but this will allow you to test your code without waiting 12 hours.

这篇关于更新 Apple Watch 复杂功能数据的流程是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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