-
Keep your complications up to date
Time is of the essence: Discover how your Apple Watch complications can provide relevant information throughout the day and help people get the information they need, when they need it. Learn best practices for capitalizing on your app's runtime opportunities, incorporating APIs like background app refresh and URLSession, and implementing well-timed push notifications.
Recursos
Videos relacionados
WWDC21
WWDC20
-
Buscar este video…
-
-
3:32 - updateActiveComplications
class ExtensionDelegate: NSObject, WKExtensionDelegate { func updateActiveComplications() { let complicationServer = CLKComplicationServer.sharedInstance() if let activeComplications = complicationServer.activeComplications { for complication in activeComplications { complicationServer.reloadTimeline(for: complication) } } } } -
4:26 - getCurrentTimelineEntry
class ComplicationController: NSObject, CLKComplicationDataSource { func getCurrentTimelineEntry(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTimelineEntry?) -> Void) { switch (complication.family) { case .modularSmall: let template = CLKComplicationTemplateModularLargeTallBody.init( headerTextProvider: headerTextProvider, bodyTextProvider: bodyTextProvider) entry = CLKComplicationTimelineEntry(date: Date(), complicationTemplate: template) } handler(entry) } } -
6:06 - scheduleBar
private func scheduleBAR(_ first: Bool) { let now = Date() let scheduledDate = now.addingTimeInterval(first ? 60 : 15*60) let info:NSDictionary = [“submissionDate”:now] let wkExt = WKExtension.shared() wkExt.scheduleBackgroundRefresh(withPreferredDate: scheduledDate, userInfo:info) { (error: Error?) in if (error != nil) { print("background refresh could not be scheduled \(error.debugDescription)") } } } -
7:08 - handleBAR
class ExtensionDelegate: NSObject, WKExtensionDelegate { func handle(_ backgroundTasks: Set<WKRefreshBackgroundTask>) { for task in backgroundTasks { switch task { case let backgroundTask as WKApplicationRefreshBackgroundTask: if let userInfo:NSDictionary = backgroundTask.userInfo as? NSDictionary { if let then:Date = userInfo["submissionDate"] as! Date { let interval = Date.init().timeIntervalSince(then) print("interval since request was made \(interval)") } } self.updateActiveComplications() self.scheduleBAR(first: false) backgroundTask.setTaskCompletedWithSnapshot(false) -
8:47 - handleBAR (DataProvider)
class ExtensionDelegate: NSObject, WKExtensionDelegate { var healthDataProvider: HealthDataProvider func handle(_ backgroundTasks: Set<WKRefreshBackgroundTask>) { for task in backgroundTasks { switch task { case let backgroundTask as WKApplicationRefreshBackgroundTask: healthDataProvider.refresh() { (update: Bool) -> Void in if update { self.updateActiveComplications() } self.scheduleBAR(first: false) backgroundTask.setTaskCompletedWithSnapshot(false) } -
11:35 - Instantiate backgroundURLSession
class WeatherDataProvider : NSObject, URLSessionDownloadDelegate { private lazy var backgroundURLSession: URLSession = { let config = URLSessionConfiguration.background(withIdentifier: “BackgroundWeather") config.isDiscretionary = false config.sessionSendsLaunchEvents = true return URLSession(configuration: config, delegate: self, delegateQueue: nil) }() -
12:02 - Schedule backgroundURLSessionTask
func schedule(_ first: Bool) { if backgroundTask == nil { if let url = self.currentWeatherURLForLocation(delegate.currentLocationCoordinate) { let bgTask = backgroundURLSession.downloadTask(with: url) bgTask.earliestBeginDate = Date().addingTimeInterval(first ? 60 : 15*60) bgTask.countOfBytesClientExpectsToSend = 200 bgTask.countOfBytesClientExpectsToReceive = 1024 bgTask.resume() backgroundTask = bgTask } } } } -
13:29 - handle backgroundURLSession
class ExtensionDelegate: NSObject, WKExtensionDelegate { var weatherDataProvider:WeatherDataProvider func handle(_ backgroundTasks: Set<WKRefreshBackgroundTask>) { for task in backgroundTasks { switch task { case let urlSessionTask as WKURLSessionRefreshBackgroundTask: weatherDataProvider.refresh() { (update: Bool) -> Void in weatherDataProvider.schedule(first: false) if update { self.updateActiveComplications() } urlSessionTask.setTaskCompletedWithSnapshot(false) } -
13:59 - handle backgroundURLSession
class WeatherDataProvider : NSObject, URLSessionDownloadDelegate { var completionHandler : ((_ update: Bool) -> Void)? func refresh(_ completionHandler: @escaping (_ update: Bool) -> Void) { self.completionHandler = completionHandler } -
14:08 - didFinishDownloadingTo
class WeatherDataProvider : NSObject, URLSessionDownloadDelegate { func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) { if location.isFileURL { do { let jsonData = try Data(contentsOf: location) if let kiteFlyingWeather = KiteFlyingWeather(jsonData) { // Process weather data here. } } catch let error as NSError { print("could not read data from \(location)") } } } -
14:23 - didComplete
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) { print("session didCompleteWithError \(error.debugDescription)”) DispatchQueue.main.async { self.completionHandler?(error == nil) self.completionHandler = nil } } } -
17:53 - Complication Pushes
class PushNotificationProvider : NSObject, PKPushRegistryDelegate { func startPushKit() -> Void { let pushRegistry = PKPushRegistry(queue: .main) pushRegistry.delegate = self pushRegistry.desiredPushTypes = [.complication] } func pushRegistry(_ registry: PKPushRegistry, didUpdate pushCredentials: PKPushCredentials, for type: PKPushType) { // Send credentials to server } func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType, completion: @escaping () -> Void) { // Process payload delegate.updateActiveComplications() completion() }
-