更新Apple Watch复杂数据的流程是什么?

bkw*_*ero 20 apple-watch clockkit watchos-2 apple-watch-complication

我一直在互联网上学习很多教程,学习如何设置复杂功能.我按照预期设置并发症没有问题.

直到初始时间表条目到期.12个小时后,我不知道如何更新它以保持并发症的生效.我将分享下面的所有内容,希望有人可以帮我填写.

在这里,我为要在复杂化中显示的数据创建变量.

struct data = {
var name: String
var startString: String
var startDate: NSDate
}
Run Code Online (Sandbox Code Playgroud)

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

var dataArray = [data]
Run Code Online (Sandbox Code Playgroud)

这样可以在手表锁定时显示复杂功能.

func getPrivacyBehaviorForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationPrivacyBehavior) -> Void) {
    handler(.ShowOnLockScreen)
}
Run Code Online (Sandbox Code Playgroud)

这允许在复杂化上前进时间旅行.

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

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

func getTimelineStartDateForComplication(complication: CLKComplication, withHandler handler: (NSDate?) -> Void) {
    handler(NSDate())
}
Run Code Online (Sandbox Code Playgroud)

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

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

在这里,我创建了复杂的模板.这是为用户在浏览手表上的所有复杂情况时看到我的并发症时显示的样本数据.

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)
}
Run Code Online (Sandbox Code Playgroud)

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

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)
    }

}
Run Code Online (Sandbox Code Playgroud)

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

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)

}
Run Code Online (Sandbox Code Playgroud)

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

func getNextRequestedUpdateDateWithHandler(handler: (NSDate?) -> Void) {
    handler(NSDate(timeIntervalSinceNow: 60 * 60 * 6))
}
Run Code Online (Sandbox Code Playgroud)

这是我遇到问题的地方.

如何创建新数据并重新加载时间线?什么是流量?我不是要延长时间表,而是要完全取代它.我完全失去了.到目前为止,Apple的文档非常模糊.我知道我需要实现以下方法,但我不知道如何.有人可以帮我填写这段代码吗?

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.
}
Run Code Online (Sandbox Code Playgroud)

更新:

感谢El Tea,我已经开始工作了.我需要将一个CLKComplicationServer实例添加到requestedUpdateDidBegin并将reloadTimeline方法放入其中.

这是更新的代码:

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")
}
Run Code Online (Sandbox Code Playgroud)

El *_*Tea 25

在一段时间间隔内完成的并发症刷新的流程遵循以下顺序:

  • iOS会调用您的函数requestedUpdateDidBegin()requestedUpdateBudgetExhausted()(如果您的预算已用尽,您所做的任何事情都不会导致更新,直到您获得更多执行时间.)
  • requestedUpdateDidBegin() 必须在内部调用reloadTimelineForComplication()extendTimelineForComplication()指定你想要重新加载哪些并发症或添加数据.如果你不这样做,没有任何反应!
  • 根据你叫reload或者extend,iOS版使一方或双方的通话getCurrentTimelineEntryForComplication(),并getTimelineEntriesForComplication()
  • 无论您是否更新了复杂功能,iOS都会getNextRequestedUpdateDateWithHandler()在您下次要求重复上述步骤时进行调用.

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

该过程以这种方式工作,以便iOS不要求您重复重新生成相同的数据.它让您有机会requestedUpdateDidBegin()决定您的并发症是否需要更新.如果没有,您的代码应该返回.(这可以减少并发症的执行时间,并有助于避免iOS因使用其每日预算而将应用程序从进一步更新中删除).但是如果你有新的数据,你需要通过调用reloadTimelineForComplication()或告诉iOSextendTimelineForComplication()

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

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)
    }
}
Run Code Online (Sandbox Code Playgroud)

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

我在模拟器测试更新间隔方面取得了成功,只需十分钟.由于执行时间预算的原因,您可能不应经常在真实手表上更新频率,但这样您就可以在不等待12小时的情况下测试代码.

  • 大!并发症很简陋,但是关于它们的信息在这一点上仍然非常缺乏.很高兴你得到了它. (4认同)
  • 请注意,当调用requestedUpdateBudgetExhausted时,您可以在该调用中再执行一次更新.它就像一个标记,再一次,你必须等待x金额,直到手表决定补充你的预算 (2认同)

小智 16

El Tea的答案详细介绍了如何更新watchOS 2的复杂功能.

在watchOS 3中,使复杂化保持最新的推荐方法包括使用后台刷新应用程序任务.您可以使用一系列后台任务来安排处理在后台被唤醒的应用扩展程序:

这更具功能性和节能性,因为它不会使用任何复杂的日常执行预算来获取数据或更新模型.

它还避免了任何未经修改的方法的复杂性,这些方法试图在复杂数据源中异步获取数据,而这些数据源只是为了立即响应请求.

在另一个答案中提供了更多信息,以及WWDC视频和示例代码的链接.

总结watchOS 3的变化

使用预定的后台任务代替getNextRequestedUpdateDateWithHandler().

在应用任务中重新加载或延长时间线,而不是在内部requestedUpdateDidBegin().