Skip to content Skip to sidebar Skip to footer

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:

  1. 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)   }() }                      
  1. 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 Notifications Background modes (in the app projection)
    • your watchkit extension demand the push notifications capabilities enabled

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's pushRegistry(_: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

truetthantivane.blogspot.com

Source: https://www.wwdcnotes.com/notes/wwdc20/10049/

Postar um comentário for "Google Cloud Print "Could Not Read Data""