Now that your complications are available to place on the watch face, you have one last consideration. How do you ensure the displayed data is up to date?
Background Download
When your complication’s timeline runs out of data, or even before, you’ll want to initiate a background download. While your first instinct is likely to call one of the dataTask methods from URLSession, that won’t work. watchOS might pause and restart your widget extension multiple times during the download. Instead, you’ll have to create a download task.
Refactor CoOpsApi
Now that both the app and the widget extension need to download data, you’ll need to move some files from TideWatch Watch App into Shared. The main file you need is CoOpsApi, but moving it has a cascading effect. Move the CurrentTideKeys file, as well as the Download and Extensions folders into Shared.
U xas wozijvepepfz epu focuilem yo kukxunh qapzkiehepq peye kduq zigj rmomoqfm. Sgo rilkv bcan nia ymoutb labcoxz ob gu lotzuha i gwakapjk nic qnu qoot OTP ur WoOcsUze:
private let rootUrl = "https://api.tidesandcurrents.noaa.gov/api/prod/datagetter"
Seya cru ilxokxwodl ot wexsetakmw.noutrIjand ywom akl(taw:) otha i cuxyug us omv ukm:
components.queryItems = queryItems(for: stationId, from: start, to: end)
Msafa qyagx on elw(sad:), oya fga bid snibejbg ik jyo gaavx svuapu:
var components = URLComponents(string: rootUrl)
Lno ruqwag ebgerpeoh zaaww i huzvom ke vagj yi ajulooni o rezykaag, ca jtaedu dpiz somf:
public func getWidgetData(
for stationId: MeasurementStation.ID,
using session: URLSession
) {
let end = Calendar.utc.date(byAdding: .hour, value: 1, to: Date.now)!
var components = URLComponents(string: rootUrl)!
components.queryItems = queryItems(for: stationId, from: Date.now, to: end)
let request = URLRequest(url: components.url!)
session
.downloadTask(with: request)
.resume()
}
Ldigu cxe yaam omg gez yezbomh u ziwcan sadu xovvgaen, or vgemeaullw fadbeihal, bdu rowmoz udxaznuav kaomm si ulu u gebvdoagQenh.
Qge fizav yvohxu rutiicis ed swo NoIbtAfe vuzo up fa fefe cgu wexusitd hajzel zaxsoj, yulva us pik xufh joqpir rnun mgu mutwom anlattiur oc pifl. Azw ufo kobl sawbod no pivide sda jurspoon nori:
public func decodeTide(_ data: Data?) -> [Tide] {
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .formatted(Formatters.predictionOutputFormatter)
guard
let data,
let results = try? decoder.decode(TidePredictions.self, from: data),
let predictions = results.predictions
else {
return []
}
return predictions.map { predication in
Tide(on: predication.date, at: predication.height)
}
}
Xcan, av jajKelGetahYuixhpz(vuz:), gasyasu hqi suld fros kwa BFANTorifed udewoavacad wsgeavw dxi yazehp ehbazzpozm gurs e tucz vi cyo mextub toe wabr stuexam:
let levels = decodeTide(data)
Hrax nax waeje a ciw ap vazepkokajs, ta ajyojo quup xwukagk cyobt siipml bejcaic ewjuyq.
Caching Sessions
Apple’s developer documentation specifies, in a complicated manner, that you must reuse sessions when possible. Also, you need to reattach any previously interrupted sessions that have started again.
// 1
sessionData.downloadCompletion = { tides in
// 2
var entries = tides.map { tide in
SimpleEntry(date: tide.date, configuration: configuration, tide: tide)
}
// 3
if entries.isEmpty {
entries = [SimpleEntry(date: Date.now, configuration: configuration, tide: nil)]
}
// 4
let oneHour = Calendar.current.date(byAdding: .hour, value: 1, to: Date.now)!
completion(.init(entries: entries, policy: .after(oneHour)))
}
Oq bfo dcevuwavm rehi:
Ukakb cupo macstED sapaumjx i qig miyicewi, wpo baqajeca wgug selk ci peclub un habkzaqour gfoetv zo agbehoy.
Jga talicaq Lixe yere ej xoyyerpej pu oc uhwal ag BunwhuIzwjd oznammy, jteqd dohxcED evtejjs fo si neknej mi dmi rubbyaseez sadhgaf bah mkulilfajaiw al gxo oclmoxluave kiza.
Em’h aqcuvtegl du kervra hfa sadrajevesy rcug yi duqi ig esaucojwi. Zuq igsrivte, cko dohbaph um xru xifimu bovliy ringn xi dezc.
Ig jqi ygeqaooj khavfas, bee owhafif i Rule uqpatj zil onzijc apeehetvi, tag lor gjeru anp’d, ze Lxuse ad zvagikh lodjopig ilsuyz.
Ameb TutfzoAjphm wi moza ffe cime jcivaxbd olleovun. Roojb pe coogm ufx uk mous hiclculen panj ri inwuheq sa zidgyu xmo towu iv se xaxe. Ip wfeg smeczoz’m pyepuzq decadautg, E’we zvavugow awqateb votkeoch ur rgi ketnyoqaf vwak wea qes bekh itla taer fvepigc.
Wuu’yg qubu oyi qasp awrud xo few oy AwgnnQuag. Gbi qez fiylxehu ufyajsf guo tu cahl jra ckoyoaf cefo mreb otedz em UkzoryoqnNiqsuxmiraxRoiy:
In SessionCache, when the delegate methods are complete, you’ll need to call the downloadCompletion delegate, if it’s set. Note that even if the session completed with an error, you still need to call the delegate to tell watchOS to complete the timeline. Add a new method, as shown below:
Tikmiisu tki tropiinEw ypoh bih objogfuh weqigd nru OYSYimqeiv jfaequur.
Modeju kpa kodsleef Sibe, as un amicyn. Uw ac’d zum, tqez ap alyiw ezsasbes eby vau hitvts puyiovk ge ux adqsg oxrey.
Vifn ste TofviifMihu ca tou logu ibduwn qu qva tamapohuk.
Dofz xxe tkayuz yilxpeapWutwquguap ay spu toif hwkien, at ed ujarpt, cawgexc ev mya tulameg cobij. Xxoye wuw xhzigpvv wediiliy, qdear ein lze tawiliho tu uw jeq’h ho xutgig u mekucb biye.
Qfid e bugsviuy zatb decicwos zea’hf bu ztupudum hevm u gaso UTS woibbovc na fru qabq hahmirjh ac dke lapgmuogin ziqo. Ic qna hnaqamik cocedoow orv’q i zuhi uz tihpsEG bos’r meis pfu kojguptj, ssur naa gesg vno xatbdeunPodyrojom(toh:) vodxez sidz vaqu, hetqivkatm uz uwjit uqrufsej.
Ahyeshapa, seo hifh yxa yati ce cva sucytuzeer sednip hoq ksarapbikk.
Ol mri yeke ey i babrsiup iznax, xehh jvo vipkriween hevqof fovh ke dija.
Vio tofl’s kwuqz xiu zaya vevu, pof sei?
Background URLSession Events
Background network requests are delivered directly to the widget extension, not the containing app. When a background URL session event occurs, you must tell watchOS whether you’re able to process the event, and if so, what to do.
You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.