问题
I have an Apple Watch complication that initializes correctly and show the data I am expecting. However, when the NSDate returned in my getNextRequestedUpdateDateWithHandler method triggers a refresh, the only method in my delegate that gets called again is the getNextRequestedUpdateDateWithHandler method (I set breakpoints at every method to determine this). I would have expected requestedUpdateDidBegin to get called when the requested update date occurs, but that doesn't seem to be the case. Does anyone know what could be causing this? Here is my code:
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)
}
}
回答1:
The endDate
is the latest date for which your complication data source is prepared to supply data. If your end date has passed, this implies two things:
The latest timeline entry would be dimmed, as the end of the timeline has been reached.
The complication server would realize that it would be pointless to ask for entries past your endDate as no future entries could possibly exist. In that case, the complication server will only ask for a new update date, as you notice.
The complication server uses a 72-hour sliding window, to ensure 24 hours of time travel in either direction.
Even though you do not support forward time travel, you should ensure a future endDate
for a couple of reasons.
If you never want your current entry to be dimmed, the end date must not be reached before the timeline is reloaded.
The complication server must know that your data source can be asked for additional entries, since your timeline is still current.
Each time the timeline is reloaded, it will ask for a new start and end date. Your end date never has to be in the distant future since at best it will be updated every 30 minutes, but it should still be a day in the future, in case your daily budget is exhausted due to frequent updates.
As an aside, the complication server does factor in the time travel boundary dates to determine whether an entry should be added to the timeline.
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.
If you're providing entries that go back to the start of a week, you may want to avoid creating entries outside the time travel boundary, as to not exhaust your budget.
来源:https://stackoverflow.com/questions/34551089/apple-watch-complication-not-updating-in-background