Apple Watch 并发症不在后台更新
Apple Watch Complication not updating in background
我有一个 Apple Watch 复杂功能,可以正确初始化并显示我期望的数据。但是,当我的 getNextRequestedUpdateDateWithHandler 方法中返回的 NSDate 触发刷新时,我的委托中唯一被再次调用的方法是 getNextRequestedUpdateDateWithHandler 方法(我在每个方法上设置断点来确定这一点)。我本来希望 requestedUpdateDidBegin 在请求的更新日期发生时被调用,但情况似乎并非如此。有谁知道这可能是什么原因造成的?这是我的代码:
class ComplicationController: NSObject, CLKComplicationDataSource {
/// Provide the time travel directions your complication supports (forward, backward, both, or none).
func getSupportedTimeTravelDirectionsForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationTimeTravelDirections) -> Void) {
handler(.Backward)
}
/// Depending on which time travel directions you support, you will be asked for the start/end dates of your timeline (or both, or neither).
/// The start/end dates will determine at what point during time travel we dim out your data to indicate that the timeline does not continue in this direction.
/// Timeline entries after the timeline end date or before the timeline start date will not be displayed.
func getTimelineStartDateForComplication(complication: CLKComplication, withHandler handler: (NSDate?) -> Void) {
let calendar = NSCalendar.currentCalendar()
let now = NSDate()
var startDate: NSDate? = nil
var interval: NSTimeInterval = 0
calendar.rangeOfUnit(NSCalendarUnit.WeekOfMonth, startDate: &startDate, interval: &interval, forDate: now)
handler(startDate)
}
func getTimelineEndDateForComplication(complication: CLKComplication, withHandler handler: (NSDate?) -> Void) {
handler(NSDate())
}
/// Indicate whether your complication's data should be hidden when the watch is locked.
func getPrivacyBehaviorForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationPrivacyBehavior) -> Void) {
// Since this is showing health data, we want to secure this when the device is locked.
handler(.HideOnLockScreen)
}
/// Indicate your complication's animation behavior when transitioning between timeline entries.
func getTimelineAnimationBehaviorForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationTimelineAnimationBehavior) -> Void) {
handler(.Always)
}
/// Provide the entry that should currently be displayed.
/// If you pass back nil, we will conclude you have no content loaded and will stop talking to you until you next call -reloadTimelineForComplication:.
func getCurrentTimelineEntryForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationTimelineEntry?) -> Void) {
// ... custom entry code
handler(currentTemplate)
}
/// The owning complication will use these methods to extend its timeline backwards or forwards.
/// @param date The date of the first/last entry we already have. Return the batch of entries before/after this date.
/// @param limit Maximum number of entries to return.
func getTimelineEntriesForComplication(complication: CLKComplication, beforeDate date: NSDate, limit: Int, withHandler handler: ([CLKComplicationTimelineEntry]?) -> Void) {
//... custom entry code
handler(templates)
}
func getTimelineEntriesForComplication(complication: CLKComplication, afterDate date: NSDate, limit: Int, withHandler handler: ([CLKComplicationTimelineEntry]?) -> Void) {
handler([CLKComplicationTimelineEntry]())
}
/// Return the date when you would next like to be given the opportunity to update your complication content.
/// We will make an effort to launch you at or around that date, subject to power and budget limitations.
func getNextRequestedUpdateDateWithHandler(handler: (NSDate?) -> Void) {
// Refresh in 30 minutes
let refreshDate = NSDate().dateByAddingTimeInterval(60*30)
handler(refreshDate)
}
/// This method will be called when you are woken due to a requested update. If your complication data has changed you can
/// then call -reloadTimelineForComplication: or -extendTimelineForComplication: to trigger an update.
func requestedUpdateDidBegin() {
let complicationServer = CLKComplicationServer.sharedInstance()
for complication in complicationServer.activeComplications {
complicationServer.reloadTimelineForComplication(complication)
}
}
/// This method will be called when we would normally wake you for a requested update but you are out of budget. You can can
/// trigger one more update at this point (by calling -reloadTimelineForComplication: or -extendTimelineForComplication:) but
/// this will be the last time you will be woken until your budget is replenished.
func requestedUpdateBudgetExhausted() {
let complicationServer = CLKComplicationServer.sharedInstance()
for complication in complicationServer.activeComplications {
complicationServer.reloadTimelineForComplication(complication)
}
}
/// When your extension is installed, this method will be called once per supported complication, and the results will be cached.
/// If you pass back nil, we will use the default placeholder template (which is a combination of your icon and app name).
func getPlaceholderTemplateForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationTemplate?) -> Void) {
//... custom template code
handler(template)
}
}
endDate
是您的复杂功能数据源准备提供数据的最晚日期。如果您的结束日期已过,这意味着两件事:
最新的时间线条目将变暗,因为已到达时间线的末尾。
并发症服务器会意识到,要求输入超过 endDate 的条目是没有意义的,因为未来的条目可能不存在。在这种情况下,并发症服务器将只要求一个新的更新日期,如您所见。
并发症服务器使用72小时滑动window,以确保双向24小时的时间旅行。
即使您不支持向前的时间旅行,您也应该确保未来 endDate
有几个原因。
如果您不想让当前条目变暗,则在重新加载时间线之前不得到达结束日期。
复杂服务器必须知道您的数据源可能会被要求提供额外的条目,因为您的时间线仍然是最新的。
每次重新加载时间线时,它都会要求一个新的开始和结束日期。您的结束日期永远不必是遥远的未来,因为它最多每 30 分钟更新一次,但它仍然应该是未来的一天,以防您的每日预算因频繁更新而耗尽。
顺便说一句,the complication server 会考虑时间旅行边界日期来确定是否应将条目添加到时间线中。
earliestTimeTravelDate
When constructing your timeline, do not create any entries before this date. Doing so is a waste of time because those entries will never be displayed.
如果您提供的条目可以追溯到一周的开始,您可能希望避免在时间旅行边界之外创建条目,以免耗尽预算。
我有一个 Apple Watch 复杂功能,可以正确初始化并显示我期望的数据。但是,当我的 getNextRequestedUpdateDateWithHandler 方法中返回的 NSDate 触发刷新时,我的委托中唯一被再次调用的方法是 getNextRequestedUpdateDateWithHandler 方法(我在每个方法上设置断点来确定这一点)。我本来希望 requestedUpdateDidBegin 在请求的更新日期发生时被调用,但情况似乎并非如此。有谁知道这可能是什么原因造成的?这是我的代码:
class ComplicationController: NSObject, CLKComplicationDataSource {
/// Provide the time travel directions your complication supports (forward, backward, both, or none).
func getSupportedTimeTravelDirectionsForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationTimeTravelDirections) -> Void) {
handler(.Backward)
}
/// Depending on which time travel directions you support, you will be asked for the start/end dates of your timeline (or both, or neither).
/// The start/end dates will determine at what point during time travel we dim out your data to indicate that the timeline does not continue in this direction.
/// Timeline entries after the timeline end date or before the timeline start date will not be displayed.
func getTimelineStartDateForComplication(complication: CLKComplication, withHandler handler: (NSDate?) -> Void) {
let calendar = NSCalendar.currentCalendar()
let now = NSDate()
var startDate: NSDate? = nil
var interval: NSTimeInterval = 0
calendar.rangeOfUnit(NSCalendarUnit.WeekOfMonth, startDate: &startDate, interval: &interval, forDate: now)
handler(startDate)
}
func getTimelineEndDateForComplication(complication: CLKComplication, withHandler handler: (NSDate?) -> Void) {
handler(NSDate())
}
/// Indicate whether your complication's data should be hidden when the watch is locked.
func getPrivacyBehaviorForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationPrivacyBehavior) -> Void) {
// Since this is showing health data, we want to secure this when the device is locked.
handler(.HideOnLockScreen)
}
/// Indicate your complication's animation behavior when transitioning between timeline entries.
func getTimelineAnimationBehaviorForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationTimelineAnimationBehavior) -> Void) {
handler(.Always)
}
/// Provide the entry that should currently be displayed.
/// If you pass back nil, we will conclude you have no content loaded and will stop talking to you until you next call -reloadTimelineForComplication:.
func getCurrentTimelineEntryForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationTimelineEntry?) -> Void) {
// ... custom entry code
handler(currentTemplate)
}
/// The owning complication will use these methods to extend its timeline backwards or forwards.
/// @param date The date of the first/last entry we already have. Return the batch of entries before/after this date.
/// @param limit Maximum number of entries to return.
func getTimelineEntriesForComplication(complication: CLKComplication, beforeDate date: NSDate, limit: Int, withHandler handler: ([CLKComplicationTimelineEntry]?) -> Void) {
//... custom entry code
handler(templates)
}
func getTimelineEntriesForComplication(complication: CLKComplication, afterDate date: NSDate, limit: Int, withHandler handler: ([CLKComplicationTimelineEntry]?) -> Void) {
handler([CLKComplicationTimelineEntry]())
}
/// Return the date when you would next like to be given the opportunity to update your complication content.
/// We will make an effort to launch you at or around that date, subject to power and budget limitations.
func getNextRequestedUpdateDateWithHandler(handler: (NSDate?) -> Void) {
// Refresh in 30 minutes
let refreshDate = NSDate().dateByAddingTimeInterval(60*30)
handler(refreshDate)
}
/// This method will be called when you are woken due to a requested update. If your complication data has changed you can
/// then call -reloadTimelineForComplication: or -extendTimelineForComplication: to trigger an update.
func requestedUpdateDidBegin() {
let complicationServer = CLKComplicationServer.sharedInstance()
for complication in complicationServer.activeComplications {
complicationServer.reloadTimelineForComplication(complication)
}
}
/// This method will be called when we would normally wake you for a requested update but you are out of budget. You can can
/// trigger one more update at this point (by calling -reloadTimelineForComplication: or -extendTimelineForComplication:) but
/// this will be the last time you will be woken until your budget is replenished.
func requestedUpdateBudgetExhausted() {
let complicationServer = CLKComplicationServer.sharedInstance()
for complication in complicationServer.activeComplications {
complicationServer.reloadTimelineForComplication(complication)
}
}
/// When your extension is installed, this method will be called once per supported complication, and the results will be cached.
/// If you pass back nil, we will use the default placeholder template (which is a combination of your icon and app name).
func getPlaceholderTemplateForComplication(complication: CLKComplication, withHandler handler: (CLKComplicationTemplate?) -> Void) {
//... custom template code
handler(template)
}
}
endDate
是您的复杂功能数据源准备提供数据的最晚日期。如果您的结束日期已过,这意味着两件事:
最新的时间线条目将变暗,因为已到达时间线的末尾。
并发症服务器会意识到,要求输入超过 endDate 的条目是没有意义的,因为未来的条目可能不存在。在这种情况下,并发症服务器将只要求一个新的更新日期,如您所见。
并发症服务器使用72小时滑动window,以确保双向24小时的时间旅行。
即使您不支持向前的时间旅行,您也应该确保未来 endDate
有几个原因。
如果您不想让当前条目变暗,则在重新加载时间线之前不得到达结束日期。
复杂服务器必须知道您的数据源可能会被要求提供额外的条目,因为您的时间线仍然是最新的。
每次重新加载时间线时,它都会要求一个新的开始和结束日期。您的结束日期永远不必是遥远的未来,因为它最多每 30 分钟更新一次,但它仍然应该是未来的一天,以防您的每日预算因频繁更新而耗尽。
顺便说一句,the complication server 会考虑时间旅行边界日期来确定是否应将条目添加到时间线中。
earliestTimeTravelDate
When constructing your timeline, do not create any entries before this date. Doing so is a waste of time because those entries will never be displayed.
如果您提供的条目可以追溯到一周的开始,您可能希望避免在时间旅行边界之外创建条目,以免耗尽预算。