Google Cloud Print "Could Not Read Data"
Keep your complications up to date
Description: Time is of the essence: Notice how your Apple Watch complications can provide relevant information throughout the day and aid people become the information they need, when they need it. Acquire all-time practices for capitalizing on your app'due south runtime opportunities, incorporating APIs like background app refresh and URLSession, and implementing well-timed push notifications.
Demo app hither.
Foreground opportunities
When the app is in the foreground, we can tell the CLKComplicationServer that we would like to reload our complications timelines:
allow complicationServer = CLKComplicationServer.sharedInstance() if permit activeComplications = complicationServer.activeComplications { for complication in activeComplications { // Be selective on what yous really need to reload complicationServer.reloadTimeline(for: complexity) } } This tells the server when nosotros would like to refresh our complexity(s).
Later on our CLKComplicationDataSource's getCurrentTimelineEntry(for:withHandler:) volition exist called:
func getCurrentTimelineEntry( for complexity: CLKComplication, withHandler handler: @escaping (CLKComplicationTimelineEntry?) -> Void ) { // .. handler(entry) } Groundwork App Refresh
- Groundwork refresh allows us to schedule periodic updates to go on that complication up-to-date even when the app isn't in utilise.
- Upwards to four times per 60 minutes (regardless of how many complications are present in the current watch face)
Brand a scheduleBackgroundRefresh(withPreferredDate:userInfo:scheduledCompletion:) asking on WKExtension
private func scheduleBAR(_ beginning: Bool) { allow now = Appointment() let scheduledDate = now.addingTimeInterval(showtime ? sixty : fifteen*60) // apply the info dictionary to supply your own data to the refresh 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 non be scheduled \(error.debugDescription)") } } } Later on the WKExtension will trigger the refresh in our WKExtensionDelegate via the handle(:) method.
class ExtensionDelegate: NSObject, WKExtensionDelegate { func handle(_ backgroundTasks: Fix<WKRefreshBackgroundTask>) { for task in backgroundTasks { switch task { case let backgroundTask equally WKApplicationRefreshBackgroundTask: if let userInfo: NSDictionary = backgroundTask.userInfo equally? NSDictionary { if allow then:Date = userInfo["submissionDate"] as! Appointment { permit interval = Engagement.init().timeIntervalSince(then) print("interval since asking was made \(interval)") } } // once we're done updating the data, we enquire the complication server to reload our active complications self.updateActiveComplications() // we and then schedule the next background refresh self.scheduleBAR(first: false) // then we consummate the current job, we pass `false` to point that no snapshot is needed. // Each complication update results in a snapshot request, so we don't have to asking 1 separately. backgroundTask.setTaskCompletedWithSnapshot(faux) case ... } } } } Guidelines:
- Only one asking is outstanding at a time: if you demand periodic updates, schedule the adjacent update before marking the electric current one complete
- No networking: URLSession will fail with an error
- Background updates are limited to a maximum of four seconds of active CPU fourth dimension
- Background updates accept a maximum of 15 seconds of total time to complete the task
Background URLSession
- Allow your app to schedule and receive data even when the app isn't running
- Tin can be used in addition to background app refresh
- Up to four times per hour
- Multiple outstanding tasks are allowed
Creating a request is composed by multiple steps:
- define a
backgroundURLSession:
class WeatherDataProvider: NSObject, URLSessionDownloadDelegate { individual lazy var backgroundURLSession: URLSession = { allow config = URLSessionConfiguration.background(withIdentifier: "BackgroundWeather") config.isDiscretionary = fake config.sessionSendsLaunchEvents = true return URLSession(configuration: config, delegate: cocky, delegateQueue: zip) }() } - create and resume a background task:
func schedule(_ commencement: Bool) { if let url = self.currentWeatherURLForLocation(consul.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 } } When the download is complete, our WKExtensionDelegate's handle(:) method will be called.
class ExtensionDelegate: NSObject, WKExtensionDelegate { var weatherDataProvider:WeatherDataProvider func handle(_ backgroundTasks: Set<WKRefreshBackgroundTask>) { for task in backgroundTasks { switch task { instance allow urlSessionTask equally WKURLSessionRefreshBackgroundTask: weatherDataProvider.refresh() { (update: Bool) -> Void in // schedule the next retrieval (if needed) weatherDataProvider.schedule(starting time: false) // update complications if needed if update { self.updateActiveComplications() } // phone call task completion urlSessionTask.setTaskCompletedWithSnapshot(imitation) } } } } } } Our URLSessionDownloadDelegate's urlSession(:downloadTask:didFinishDownloadingTo:) will exist chosen with information on the downloaded data:
class WeatherDataProvider : NSObject, URLSessionDownloadDelegate { func urlSession( _ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL ) { if location.isFileURL { do { allow jsonData = effort Data(contentsOf: location) if let kiteFlyingWeather = KiteFlyingWeather(jsonData) { // Process weather information here. } } catch let mistake every bit NSError { print("could not read information from \(location)") } } } } After we process the data URLSessionDownloadDelegate's urlSession(:task:didCompleteWithError:) volition exist called: call the completion handler on the primary queue so we dispatch to the principal queue and call the completion handler.
func urlSession( _ session: URLSession, job: URLSessionTask, didCompleteWithError error: Error? ) { print("session didCompleteWithError \(fault.debugDescription)") DispatchQueue.main.async { cocky.completionHandler?(error == aught) // set the completion handler to nil to make sure information technology's not called more in one case. self.completionHandler = zero } } } Guidelines:
- Background updates are express to a maximum of four seconds of active CPU time
- Background updates have a maximum of xv seconds of full time to complete the task
Complexity Pushes
- Servers can send up to fifty complication pushes per mean solar day to each individual watch (no limitations on how frequent they are, aka they tin be 50 pushes in one 60 minutes)
- The server needs to have a valid push certificate:
- crate a new app (complexity) identifier with id
{{bundle ID}}.watchkitapp.complication - create a push notification certificate with this new app identifier
- your app needs to enable
Remote NotificationsBackground modes (in the app projection) - your watchkit extension demand the push notifications capabilities enabled
- crate a new app (complexity) identifier with id
Annals the complication for push notifications
course PushNotificationProvider : NSObject, PKPushRegistryDelegate { func startPushKit() -> Void { let pushRegistry = PKPushRegistry(queue: .principal) pushRegistry.delegate = cocky pushRegistry.desiredPushTypes = [.complication] } func pushRegistry( _ registry: PKPushRegistry, didUpdate pushCredentials: PKPushCredentials, for type: PKPushType ) { // Send credentials to server } } Receiving Push notifications
- The app will resumed or launched when receiving a push notification
- Our
PKPushRegistryDelegate'spushRegistry(_:didReceiveIncomingPushWith:for:completion:)will be called - This part is chosen in the queue we specified when registering with PushKit
- Think to phone call the completion after processing the notification
class PushNotificationProvider : NSObject, PKPushRegistryDelegate { ... func pushRegistry( _ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for blazon: PKPushType, completion: @escaping () -> Void ) { // Process payload delegate.updateActiveComplications() completion() } } Guidelines:
- Background updates are limited to a maximum of 4 seconds of active CPU fourth dimension
- Background updates have a maximum of 15 seconds of total time to consummate the task
Epitomize
Source: https://www.wwdcnotes.com/notes/wwdc20/10049/
Postar um comentário for "Google Cloud Print "Could Not Read Data""