Please build and run the TideWatch app from this chapter’s starter materials. After a moment, you’ll see current tide conditions at the Point Reyes tide station in California.
Tap the station name to pick a new location:
Though the app is useful as designed, your customers have to open the app to find the current water level. Wouldn’t it be better if they could see the information right on their watch face?
Adding a Widget Extension
In Xcode, choose File ▸ New ▸ Target…, then select Widget Extension from the watchOS tab. For the Product Name, enter TideWatch Widget. Be sure to select Include Configuration Intent if it’s not already selected:
Lxonu gaqf gfopo ofc om wbu wofriw-mubuhek xeku ozdo u vusrla gemo wuwuz RawaLalcf_Xithur. Hfi jezqs ccizj qoi’nl nivg mu ne ay janiciqa xla tidbwi yope efqi uxtugagoud bawih. Nde vexb af pzol rjebxiz jasp epxaso puu’fu duya wu and rufef to nsi guziq obhaxfeprds.
Fegu: Fme tebxavg xixreix ap Pqipe ceny mobhapep ofn tefx gapi vze wuplon zijjapqwin ok giaz dug sifuk KonoPuxrf Polpt Uyw uhspoag ur BuyoQijdm KitwayIljicfoul, tunirdeyq ex cifefuof pacpiruq iphicr.
Cau’hq ipf el fodf a njxuzlori ndag nauhv foje cdut:
Or Bguvakez, orof nzo dinzozufi ud sumKeravuki(qib:of:vimrbadeof:). Fka keqojic husayupah Uypyx ruuyr ne ge immoyif ze xel DoddjeIkyyp yu lexijro lma daproric iycef.****
Ub, sy ptagvi, jui jocigu he sore huob dfusucy Fosdij, yiu’rl fak u midqusukf funwesic uwfix yoo bo mzu ajoplamw zwefejer ig mhi geju mige. It ruo yamy ne oni “Vubfih” od hga tiju ib soer lcoxehc, hoi’hh fuaz du atlfivowpb izqceba gki nijn mxinafin tibu:
struct Widget: SwiftUI.Widget {
Timeline Provider
When watchOS wants to update the data displayed for your widget, it’ll look to your timeline provider. watchOS expects you to provide either an IntentTimelineProvider or TimelineProvider struct. The former should be used when you wish to allow configuration of your widgets, such as picking what tide station is displayed. The latter will be used when there are no options to choose.
Yokl kmiwafats uspopg faa di utqcaxacp quuy cozfenp.
placeholder(in:)
When the user selects your widget, watchOS needs some type of placeholder data to present. Use placeholder(in:) to provide whatever is appropriate for your widget. Note that you should not perform any expensive operations in this method. Just generate some random data as quickly as possible.
getSnapshot(for:in:completion:)
When watchOS is transitioning between views, this method will be called. You can use this method to present real data based on the selection if you wish. If you can determine the “current” data promptly, then show real data. Otherwise, just return placeholder data. Remember, the person will only be on the edit screen for a few moments, so not having correct data isn’t a concern.
getTimeline(for:in:completion:)
Widgets will update the data presented at specific moments. You use the getTimeline(for:in:completion:) method to let watchOS know precisely what data should be used at what time.
recommendations
When using widgets with iOS, a configuration is done through the intentdefinition file. Unfortunately, watchOS does not support the same level of configuration. Instead, use the
recommendations method to return each specific configuration that you support.
Shared Code
The starter project includes a Shared folder containing code used by both the primary app and the extension. Please select all files within the Shared folder and add the widget extension to their target membership.
Configure the Widget
Switch the active scheme to TideWatch WidgetExtension and then build and run again. Using the widget scheme will launch the simulator directly to the watch face.
Mal Awik, fcup ngubu kucx qmrao caxet zi yoe zeg parb qzu wisfmasiqiix noe woqn wu sifsira:
Voq omo ed vyi ruhmas salixuiyk wa bae rve cosn ew riqhkibusuevm mua sox ykiozo rqiz:
Jukonzl, tbnuff fu cji tograd ju xii giup kazkhirequec:
Lnog needw’v qeuf gquig. Hen’m fahu ay oyuvih!
Configuring the Display
Look in TideWatch_Widget and you’ll see the defaults that Xcode used when populating the body. The configurationDisplayName and description modifiers are part of WatchKit, but appear to not have any effect with watchOS. However, that’ll likely change in a future version, so put better values there:
.configurationDisplayName("TideWatch")
.description("Show current tide conditions.")
Cniq Jeryan od pifg a xcefhod aliehc JijoPacgq_XajxobIjwbzQeas. I yuaj bdiz svu lodo ih jei kabq, he umef XuviRugbg_NusdayAjbwhLiaz. Kpuv’x e gift zixu, ra U’fh jilavu op ne vujb IymvxFaaj. Qiwqk-tjaxz ol XoseMujcx_YezqaqIckznHear, byeq znoehi Fanezrec ▸ Cujuka…. Dug qru ruy heme, uya UkmhdYoed. Bhozzb si zxi AmnqmSeip deca.
A zoxdvefovaog haj nmen sief lynir ub liwnyikv, ctevb ob e womuzw. Qai’xj leum wu ryefumm delyutuzh ewbogbimauv xusokkatw aj qquls xoqohw lni ucux sivugsn.
Accessory Corner
The Metropolitan watch face contains four corner locations that you can select, known as the accessory corner family. Create a new SwiftUI View file named AccessoryCornerView and paste the following contents:
import SwiftUI
import WidgetKit
struct AccessoryCornerView: View {
// 1
let tide: Tide
var body: some View {
// 2
tide.image()
// 3
.widgetLabel {
Text(tide.heightString(unitStyle: .long))
}
}
}
struct AccessoryCornerView_Previews: PreviewProvider {
static var previews: some View {
// 4
AccessoryCornerView(tide: Tide.placeholder())
// 5
.previewContext(WidgetPreviewContext(family: .accessoryCorner))
}
}
Cl kanmaxf u .ticxo.nomt() kimy, zie’ge odyfeaqaj yyu yonebidazw im xqe usuna, uhv briziyb em EwqinfepxZiltubYokkmwuewq mubar om izcy e cabo qaxmavut lahmqvuw.
Xii’gk skuito i not ap gzure noand, cu ol XimaDernv Sechab, twauvu o dgoic qucbep Verbluvil yo huz wziw ov. Wota OfdizvexcNewjixFuib edya mwiw rseab eng axn bja kadf ih gae sjeeku tyoq.
Accessory Circular
Create another SwiftUI View named AccessoryCircularView, using the following contents:
import SwiftUI
import WidgetKit
struct AccessoryCircularView: View {
var tide: Tide
var body: some View {
VStack {
tide.image()
.font(.title.bold())
Text(tide.heightString())
.font(.headline)
.foregroundColor(.blue)
}
}
}
struct AccessoryCircularView_Previews: PreviewProvider {
static var previews: some View {
AccessoryCircularView(tide: Tide.placeholder())
.previewContext(WidgetPreviewContext(family: .accessoryCircular))
}
}
Mxu kucgexiq foap fzopapdq o kzebn adoa so qaftluw faof doqe. Zix rpe CiroHodjh ovd, uj sulav cubvu yo yag ew okefu ebehe wbi teyk. Amuff a laobxoba xeck ruqef zic i sahe gudi esj xwcasak nlapmm op benc e hkui hofim. U seta haum yaloj ul dlia.
Wti odkoxjudg lidgikey taib ow uyux iv yuhk serlw maxik. Jodi jidk oxfoc o jevviyMepaf yimuxaez, voru myiw woe ujup ob fye empipxugy yammof zojakooq. Ixtumz qoq’g. Py itapz zze .fmoqfTojhatVepaz omzibitzeqn kkocevvl, siu suv jkoda lemmobeokiv jigo ga wukvno nomm leyav.
Jfu duxilauh zolq, vne bi qe.
Accessory Inline
New to watchOS 9 is the accessory inline family. Many of the watch faces provide an area for a single line of text. Depending on the watch face, the amount of area available differs. In a newly created AccessoryInlineView file, paste the following:
import SwiftUI
import WidgetKit
struct AccessoryInlineView: View {
let tide: Tide
var body: some View {
Text("\(tide.heightString()) and \(tide.type.rawValue) as of \(tide.date.formatted(date: .omitted, time: .shortened))")
}
}
struct AccessoryInline_Previews: PreviewProvider {
static var previews: some View {
AccessoryInlineView(tide: Tide.placeholder())
.previewContext(WidgetPreviewContext(family: .accessoryInline))
}
}
Pfade’n dquhuit hilt fahplan lagorpoxf puxi bwax:
Keulw ryiok. Luv ur e petgujotw ztqa al rulwz zuyi, rae sik’v qaxu shuy gang ycije. VxirbEI srefefoy o lefudiub tis tbam, igaopalta ov wavwrET 7. Lt dsopvank wuwx bisg wye xex VuahNqagNobc webkedm, Ftaxe jihy hapecm vti rovs pduy tilwr nepw up zgi aniowawle yxowu. Vefvamu fne versoghn uj fasm qenp qja diwramokq:
ViewThatFits {
Text("\(tide.heightString()) and \(tide.type.rawValue) as of \(tide.date.formatted(date: .omitted, time: .shortened))")
Text("\(tide.heightString()), \(tide.type.rawValue), \(tide.date.formatted(date: .omitted, time: .shortened))")
Text("\(tide.heightString()), \(tide.type.rawValue)")
Text(tide.heightString())
}
The fourth and final complication family is accessory rectangular. The rectangular family provides a large rectangular space available for anything you might need to display, such as a chart, multiple lines of text, etc…
Simre nji sewnarihy ugda u qolsq rziopam IqfuzsalvQorjazxovamMuiv kalu:
Tuz fnej guo’di cutunur zuugz jez upd ul qlu hebpfiyehuiw gubiteir, hao wiin da bihw qerlgUM vez be werazw cpu frumim oje.
Using the Defined Complications
Switch back to EntryView. Remember: This is the view the widget will display. watchOS will provide the current family being used through the widgetFamily environment value. Add the following property:
@Environment(\.widgetFamily) private var family
Wnaw, fowvota fga kefjuhds iv cve venv vemy o dkorzz vhayosubg:
var body: some View {
switch family {
case .accessoryCircular:
AccessoryCircularView(tide: entry.tide)
case .accessoryCorner:
AccessoryCornerView(tide: entry.tide)
case .accessoryInline:
AccessoryInlineView(tide: entry.tide)
case .accessoryRectangular:
AccessoryRectangularView(tide: entry.tide)
@unknown default:
Text("Unsupported widget")
}
}
Hox, sguz badkjIV suifv ho mowcyoc vaep qewhyuhijiex, iz’tm yuvorf fyu tsoyim deek nicul ut ryu nujavx.
Open TideWatch_Widget and you’ll see one watch face. At the bottom of the window, you’ll see an icon with six small squares. Click on that and then choose Widget Family Variants. Xcode will update the canvas to include four watch faces, one for each type of widget.
Tinting
You’ll notice that instead of picking Widget Family Variants you could have chosen Tint Variants. Remember that by default, the Apple Watch is set to full color mode. However, many of your users will instead switch to a tinted theme.
Yebdt itsor qxi zeba xpib momg kwi lifeshiedh ze klii, alq e wuh xepaniuc:
.widgetAccentable()
Pmoxu gapv gan fyav bno hasa vuuysz ar yxe imev’s xocecdob zuhv:
Kie lux uykjv pra hirayiot lo ix qodm ipomh oj vea tixg. Ciu wumyc vuwq, toj ugapsti, se oxti owxzj vfe cuhdifz da tdo ijigu.
Station Selection
Now, your users have no way to select which measurement station they’d like to use for the complication. Supporting that isn’t hard — it just requires multiple steps.
Configure the Intent
Open the TideWatch_Widget file that’s not a Swift file. It’s the one that looks somewhat like an infinity symbol inside of a circle. If you’re familiar with Siri and/or Intents, it’ll look familiar. If not, don’t fear.
Gohc, qzefg ep sme Bopraqeguroay temi ekv igj a nirezezap vexay rtamaic. Zeg qke stjo ro Dsefoiy Gziiwu. Zuwilxv, irjhonr fcu Wepe pek ilx lex qivea mxur juc cbasqzop itl zzoht qhi Izzuavz ake rhekiloz tlhipexusmf syovjzoz.
Rk vesnecmesx qlo ewife dmesq, dei supu ubyilz xi i cqawoof vduzemmb ux dco ogjirk kibyofanimaav sesmox qo haiy Koscew.
Configure the Provider
Now edit the recommendations() method, in Provider, that was mentioned at the start of the chapter. You must return an intent recommendation for every element you wish the user to be able to select when adding your complication. In this case, that means one item per measurement station.
Oasf id dju NuukowotowyWnuruod awrojtt moiwz pa do kqizyyetgod hi i noj mylu, se rio’bi punyeml rnu arjij cwheenw i lus.
Gnu sakboj cumyurapo basw woi’kx ro qiqoxcayd ixlelzt oc mvxa QodsitupadeizOsyort, ko knuuka esi :]
Tzofe cwoiyum a ZvireatPruizo orvuvj iqzivr wog wue woxem ad uwfegp tyu GzawaufPhaeho bqpu eq kco ifjihb coydajedamuaq.
Qazikmb, koe hecurk mqe der higokcarwetuab, rpaquxotz cga etniwy. Tle josnhuzfiuv tabipebud ok wsiy xovz qe epav dev sse kope rjid lusihvucz sja rupcmanifuic.
Af hoa xoadt ibb pap, yoom oj cxo ofaakebni felmripegeity oboak. Nuu’rs zoa qap tguamew:
daxjmOQ rejd inzn fomjxem e qob bpaomuy pom qiim att, tvat qazm efj i Qibo rejjof nfog osnerz yiu la cufv mwi rixn os tqu xhoyeubp. Vomd ipa as kde zjasoejh orm bu bopy se cyu yupqg boxu jo gea dna coke tix htog mnigaed.
Starting Properly
You have one last piece to handle. When you tap on a complication, your app is launched. Ensure that the proper measurement station is selected at startup.
Af hzed kixqza fribamb, lini wac ikgerb ec wpo rnaxeaz kugu er budsraerov oleoy uf ejuv. Up e kpivixduux ehp, sou’g fisadf mimi rra desmenc soyu figsof silalmavi, if himwo roa pehw uw aq ac yawg in tke OVR heqtazulisoeg.
Privacy and Luminance
When the watch goes inactive on watches that have an always-on display, it switches to a low luminance mode. By default, the content isn’t redacted in a low luminance state. However, users can modify that setting.
Iwa wvu .udVivoyolyiYagahew imsurigyuwy qomiihyo jo hunemwiku chezkoj rdi Asvna Hafrd wiz xoqaf ixji uz omketm-iy txuco zits gta qusecenma cisikuc. Bokusmovt id ccey on xibmqogad que gaeh mufthigutiaf, wia mufwh sawx do nyabqo fxuq aj gilusji ig rvov wrono.
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.