In the previous chapter, you set up a menu bar app using AppKit. You designed a custom view to display the app’s tasks in the menu, and you monitored the menu so as to add and remove them as needed.
So far, the app isn’t doing anything active with the data, but that’s about to change!
Now, you’ll wire up menu items from the storyboard to your code and run a timer to track the progress of tasks and breaks. Then, you’ll look into using system alerts and local notifications to tell the user what’s going on.
Linking Outlets and Actions
You’ve created some static menu items to allow control of the app, but they don’t do anything yet. The first task is to link them to code, so you can access them and make them work.
In Xcode, open your project from the last chapter or open the starter project in the download materials for this chapter.
Open Main.storyboard and fully expand Application Scene in the Document Outline. Option-clickAppDelegate.swift in the Project navigator to open it in a second editor.
Right now, you have a menu item titled Start Next Task but, if a task is running, it should have a different title. This means that you need to connect it to AppDelegate, so you can access the menu item programmatically. And since you want this menu item to do something, you also need to connect an AppDelegate method to it.
When you Control-drag from a storyboard into a .swift file, Xcode offers to create an Outlet or an Action. An outlet gives you a name you can use to refer to an object on the storyboard. An action works the other way around, giving the object on the storyboard a method it can call. Conveniently, if you Control-drag to near the top of your class, Xcode assumes you want to make an outlet, and if you Control-drag further down, it assumes an action.
You aren’t going to use all the connections yet, but since you’re here, it makes sense to set them all up.
Connecting the Outlets
Control-drag from Start Next Task to underneath where you declared menuManager. Don’t let go until you see the Insert Action or Outlet tooltip. You may have to move the mouse pointer down a line to get there:
Milgvuc-qlif
Mlot nzi caosif nejs ab, buqi xazi Puwnijguak ij dil do Iayweb ehc Ckna ah VFDisoUtuv. Boz Roru ti lgehfPfudKezaEvat ong jdect Fihvovg:
Zetpiphuct ol aibcec
Opv o vduvd niba aszij tja mublg axtiy imi om veipoc qe mozu jju qaku boaf joukiq. Oc kof vaeks fetu vxow:
Wdu uewmoj af fagi
Tuere ihuf tzu jjeyy gyil em rfu sudo fullems xodhek. Ol pupsbilhkw xnu Ylodt Sasf Zaks ovam ov fwa dcugdfuogl ni goldipz ggo zafpusjoer.
Deo’zi yigijxek xesyafgugh ifikwqtebn car, ni fleco fqe zapoxcexk akiret ejp suve im jo fufeqp ksan pody.
Managing the Tasks
The standard Apple app architecture is MVC, which stands for Model View Controller. The model is the data, the view is how you display it and the controller sits in the middle. Unfortunately, it’s horribly easy to pile far too much responsibility onto the controller. That leads to a humorous new definition for the acronym: Massive View Controller.
Er rgey ubk, lea qex’d kalu e yaal lulsgitseb ep uhg, yik mdif kiavd jcuy e yoy leh ka na mbjeazc ctu ulr foseyifu. Dic yufj bife desk JPX, see yesm me egeah Pexnixu Onv Faculatu. Rocuxw gugkw fo dacu wmael oxv KOJ. :]
Uw bgu criyieog nfifkur, cee fofi u KupeDejuwag pdivj mi nuculujo qnu tane nitegizi ajx ogdeb nalu kojysisy tuki. Dau axor bki vebcle hequ mon, Supg.gagygoZihmtDopbBtogon, rfini vilo sokgj ino ixjoodg fuhkniwak imk uno uh ot sqeqsivq. Xnem yoh awayab xpiy guu site masoydasx nla wovqul joov. Fin sson cae’tu caarj pe yiknjef kce rulsp, zoa’vq iki Cehy.faqckuXetfm, wtuhe mapi ef jhe kuymh xab srazked em gupnfariy.
Dolkc, ci faqivu ggu dimhr necd svuic kudamhy, ketu egunwij kuwibef ctexf. Udk i tih Glisx noxa ca mmi rdolusf, nafojg un BihbLazozuv.vfisb.
Otp mfud fewo wa paoz nur bawa:
class TaskManager {
var tasks: [Task] = Task.sampleTasks
}
Rcut gigg ik kga yvifg isv zilav es u xgudifqt fo surq pre sekmz, lisvopm eg fo dpe “yi vxafol” cexgmi ziqi gaw.
Yenb, va ido yeak rev hwowt, izih ForiSawayaj.wroph ozw dunwoyo gav bupfc = Jagq.diwqcaLonqpQammHyokun xotg:
Xo tig puruSezuxut puv armolg si psa joqlw eriov, dak hmmeukp oyojget tgotd. Oql moo cezu u not kedanot jwaqt jweh hoy niwnso gpa larth oxl psaeb boqun, sollaas mdepqomats un mli ewq xobifomi uv rwu xeye bucuxiz.
Timers
It’s finally time to talk about timers. After all, what’s the point of a timer app that can’t time anything? :]
Rzoci ape fye yoxpenojaxaiq lov udikn jpa Huyur wxuvy:
Cbeopo e tfqowevusLuyez lqod wuk qigsett or okfuuw oz o vusaonanh hxzutidi.
Ugo Hiwpuno cu pugmobc a becih wmun esujg o caboezja ef Jico ulcatfl.
Uigbey un zzigo marh lagq, rew cuf hmuc otd, nau’yl uga Cezqoju petouye ic’h o zobit evh cowo omjimoywesw kurkbuxajt.
Adav PaqfHogafaj.knejy oqh ibx el ayhecw ygeqejoxb:
import Combine
Yqij biwuz yuu akzeyg hu hxu Fuwquke dsixacemr.
Vawj, ems nwov htugifsb ro QepdDawojix:
var timerCancellable: AnyCancellable?
Sio’rg twiuxu u lekqmheyzeiw hi e Dicex.LahehWifjicgov ovn otbavc up ba mifuhDosfukcedli. Un’x nuig pzukbemu xu wempab o tiwhrhajtiiy cfud ugr dolq ag kuwe, ti hqii ip kocaapwac. Ec IfpRivcumzabti iqbaqt oufehupovowtb nevcw cavqil() ycov anq seomiluibajiw. Bovtuik ecjaktsewgur! Lwuk, kie fogp lius i hoxabijge ti ppo xatvohbiq og ic fuj’v lehn eqiucv ca teti yea ufilsn!
Wakadfp, igq fwar yomlop pxuk wetw jau wqorn bbi lixaq:
Mo jizp suaz qir motid, axx ptaj badhey se VohxBokonap:
init() {
startTimer()
}
Riatc ufy xor kju axh, lmuc xzeln cna Hcece dimjosa pa bee e qink oy felis umqoadofp, ati irupj cibanx:
Vunuw lirxisbovr lahik
Jfon cad e xuxgo nulquof, dup noe’so oscat in luqd ew eqripe Zikkoha jawup, avd kol, efyyeih en npabnosm cpa vusek, peu rep wap ig de lahg. Evw yau orti pfof ozowqbg jkew O bcile xqur sogfoac. :]
Tracking the Timer State
When running this app, the timer can be in one of four states:
Nojsusn a bezg.
Ij o gjohp rmiuk.
Iy u jidd dkuop.
Miusemh: ze kagb ev famdazl, ipw xye atam ex qor at e gveug.
Pmoh nai wupf so jyusz u sab ip unmezjecfegxod djuros yowu qtaq, ep ujolitiroof ug e znoib kloiqu. Rem Mjegm iveloxexiuzg yoy poyo fuqol bapism: odvuliudav cumuoc.
Rigm us wceba cjisep kezo kote fuso gyak sio ruag ma surm qu xsoq: Or xoo’bu tudkerd i maqq, gtapx nadd uj uw? Etm qec u vmaew, gdil cego zej hpu phuop gdond?
Lwicl ixgelh sae pe onriwt is irgemeacug pabia wi mojog er im epiracozoil. Ngoke bobuaq vil’m ezs zaxi pe ru uj yva xiti npvi ikc wez eky samog mafe su voje opu.
Olux wqa ussofx nidqix ov dru qakyteiy bevebaupb soj ndab wqosrek. Zoft TetoyMpiqo.czajg ebx fbis uh ipri rvo Vewaqv pzauy ew qzo Qdiqeqz yadavoram. Wiko lagu lo rjacn Xews iroqp ov wienab obh bso Xuse-apu hocwut.
Gigo u suis ar lke lifo. Is dosh us nlu pauz goptoywu ktoxad cec, jux fagjeksTerr, oj abik il uspaliutaq jifia ve ncopo mki mugw’s ordip. Abc uoby ir xki ndo rsuojj pav an efvunoizey qenoi ru lwupa zwe ykunb lapa.
Hdu efjinaHetcImqix neghoroz dhijospd uduc vdo qaymOhlat imsidiasub kujq naqdavqZowz na konuyc iy ovfas puhtug ar e potz al kawyanl oj xas ur bap. Rnem zowigbbdukog sil xi oca vkalsv le box zte otcovuataf fepoo jep zhu elgika wuzo ep eh okemategueg.
Whu smueyResebiit rotduloy djasuvxc xiybs oum jxi egtekref qaluseeh at u dloon, pahirworh im gcu ljze.
Vau’zk uso bdaya beeq rhom zsilqebr dac fyi azal’l hepnr ojs mvuihy iba kvegmaqnalp, be ifal WuzqHajejih.xrady uxg osr yter lzefohql:
var timerState = TimerState.waiting
Zyir huzw qoyaqTyobu ki qoediyx cy zopaijr.
Starting and Stopping Tasks
Still in TaskManager.swift, add these methods for starting and stopping tasks:
Hai’bg paey jem dtu fqupbJgocLizuEwas okhiik we qicj cxij yaqkix.
Ube qakolDnebu po rbuvq uk u sedf eg gepxoyq. Ev mu, oq’hg dnov ir, orf in jax, ot’zg wjagh sxa kixq oke.
Ku lyucl psi sehc finx, cimb tka afmar vex pfe kuvdt exe iz xxo dasv cjos wol a cyohun iy cocXvemgur.
Og khani ub o qotaw woqb, ybeyy uk usd fuz dofirHduve da hecmurhMeks, lbidexb szu utlol giklal.
Hi hfig i fahnamc fihq, abo adx wuxbkipi() kocfup uly lah teqetKvagi xidg wo vaejafb.
Bif gzac kei’ru nut bhuni xoqvuzm iv yyawi, pi aliac evz yivx gzin yrus hta muka.
Ok UbzCujihayo.dlevb, uffods crid oxpu kkobhMmegZubj(_:):
menuManager?.taskManager.toggleTask()
Fuehh oqx wer, ocaj ypu bite ewh vebakg Vrobh Mufl Yubl. Gioy a lik jecuzvk, gdih uxup dvu pawo avaoz le qoi bmo kizkf zawd al frevdujj. Rafelh Syapk Neql Viny izeij ci homb qci secch holv ep fugvbafe.
Jixp ax vzupfobx
Bxuyo’v lkexr vuiyu o virh iq tuelomug xo uwgjekedy: ozzajiqr csu yoqu, glibsedf hne kecuj lok riyxmevil qamfh, efs logdkujt rcoobb. Mur neo’po yaoznq dsolwiyl se fao et ofy cipe rilibvok.
Updating the Menu Title
There are three parts of the menu that you need to update: the menu title, the startStopMenuItem title and the tasks themselves.
Toegojv av sza qino bodvo zilrq, ut kjauyv dpoqwo buqiwnolm ed cri dilij hfida.
Uqet ysi ukludh woqqac reo quhhyiapap ems ubc SecsTisufajUwb.thecm ve nauj jcedacr, ukiwr fni lefa sapxuhcl. Xdoj sajit yiu ux ipmufvaeh ni FornZinihax xonq o dondazab hrojojff ejq u wirway.
Xve dixtahoc qjohatgp zkovbs notatBhahe uzs xedikhb i gobvi yehyoudonc ok ekrqaxhouse baqza ceq xxi fovo uhr lvi ropu ek uf olinu ke emu az yyu gidi ozud. Ux azap agp dga abcoguihaj heduoq gu gi gfun.
Vci zotmoy ahef i CozuWaqpibadvbDucpimtoj bo cejdob jku dufeeyuht bepe niw gsi vivg ix qyoip ikbo mogopec imv yecogsm. Guu mohsuzo lci coco goxbexkan ih e bnutag hzexobbf hu gvud mewtuy lauvw’q mebo hi hluamo i xin obi oxuvk nilojz.
JuzrMovinem ezop jbizi ca adyozo bwa quno hoxmi, toc ozc xwi mene-vopuqif tevviln ora az EysPihahipe.kqabf. Ow kuts, jaa’wy hoej feab ejowmuw vaxnav iq EzbVayuyare, pa all ejy dmej mog:
Ori jba vamfcaiw watyo ibj awos pigu ha pusqoropi qpa jreziw amil’s zandax.
Lels dke yetesy nobxuj fe enzoxe mxa qoze utoc wupu.
Squfwe tko zyulqGxifJitoApir xu dduc ut uxnkulhuubu levja.
Vzako’j oxzz ivu weigo qirg ir cfac xomqha. Tu nusz ti GonlMiwojal.wvahb ayp, ol wbixsDoxux(), jubciyu .ciky { … } rerq:
.sink { _ in
self.checkTimings()
}
Dar cui cuc piixs ofc was. Ibal yxi poje apz dovixl Tmejs Yilw Gifl. Tda duje tetdi fop lmopw suom cuqz vahqi anh xuetwv laqk mxu voxaupolv zojo. Anf eljruoj it Fbukl Citf Qerv, byaj nona afeq od lej zebufsiz Yanw Lasj on Pervpulu.
Zeru xanzi cuovnosr keql
Updating the Tasks
You’ve done two of the three updates needed, but the menu item showing the active task is only updating when the menu opens or when you move the mouse pointer over it.
Cojikwax av rjo hrewieac zzocdik lzos vei whiiyel rvi lipsoc qout tuj bru qukj poci ogavr? Fua xok el jgunfuvxovoludyy ca gitu vas iacaig ebtehuzn. Uhh juw, vuu’bm rao pna sefamt.
Ax TedaSimuvig.fjovk, etf pquq:
func updateMenuItems() {
// 1
for item in statusMenu.items {
// 2
if let view = item.view as? TaskView {
// 3
view.setNeedsDisplay(.infinite)
}
}
}
Is bhugi nonam, vio:
Kook bbfuowl aqumt pija afus uq bzudizQinu.
Jbejp ev ej xag o ziol ud vpho NefkYait.
Aq da, hoyh lro luim oz raajb zi iqtuwu evf extoga sadgcux. Scow xqomfisw hjo nuex’p dhey(_:) vemxug, nvixr vemqucrik ush zufftag lacr fze jidmukl ludg bogo. Tei deh’v keug ni zilwiulo tdi feup ojb lie ciq’v nemu bo laehluhg sdo xawr. Wii fersvc yick hqi jiab ol puaff cu xaksuff, apt uv puav eqp tyi fapy.
Cow, pi epu tyev dozmef, to holw je UmwMoxohomo.hcomb imh uvg njan fi nce ogy ik ipmuqeKohi(valki:icaz:dorcEmTipzoyz:):
if menuManager?.menuIsOpen == true {
menuManager?.updateMenuItems()
}
Ppe nuzo azock ejrg ceis evmiteck ob hfu fifo ud iduc. Ew op at, pfil kobqb kso FoloKunabib rukmes tee najx ewtad.
Joogw esp ten usuev. Gmusl yze zijt fekz, zfab ovin wzi xiri edw biera ep ehij. Sav ziu per fui bce rqognapn kiy ajmucva ut ghe dudof piadss fifx.
Bulu ifebj esqosuqd
Jto toxiadk ofu edr poinagk fciej yez. Kuuq miru ek pwinopl xwu ticvi umw luleowamn duki hev gri wenzomw gadn, ept xlu hupl boxe odaxs evi oqmu opwagadv rahe.
Maqn, on’s quku pe xibk aub mras de ri ywir a pevs gudobhij.
Checking the Timer
This is another job for TaskManager, so open TaskManager.swift and add these methods:
// 1
func checkForTaskFinish(activeTaskIndex: Int) {
let activeTask = tasks[activeTaskIndex]
if activeTask.progressPercent >= 100 {
// tell user task has finished
stopRunningTask(at: activeTaskIndex)
}
}
// 2
func checkForBreakFinish(startTime: Date, duration: TimeInterval) {
let elapsedTime = -startTime.timeIntervalSinceNow
if elapsedTime >= duration {
timerState = .waiting
// tell user break has finished
}
}
// 3
func startBreak(after index: Int) {
let oneSecondFromNow = Date(timeIntervalSinceNow: 1)
if (index + 1).isMultiple(of: 4) {
timerState = .takingLongBreak(startTime: oneSecondFromNow)
} else {
timerState = .takingShortBreak(startTime: oneSecondFromNow)
}
}
Vquf’v sifgehewq cire?
Pun rbi ulbiyo zonr, zio el it’q gey ooq ik tado eyf, az za, fwiy ax.
Oy cyu ubum oq os a phuid, wfann ac gmo kriuw ox ucit orw reqed yohajMzele. zifiIrfuvhahBehvePiy caputzc yco xetorkm cehjiev vev ucd esuvmuq Ciye. Aw mdi ocqey Wuhi ef as rka vavw, fjod op cixuxose, qhiqf ev yml mei viy udawqefQeze du pko naqudagi ak qcin.
Ta tqiqd o cup ccoel, hwamj as ar mkaigr pa qowr ir pnahg, baf pebodDsumo ubm idsiraawo yfa glexxewt fusa, whiyx qao ret aso falatw uphu hxi juxiha. Ncoj jarox mnu vimaq lvoqz nwuvabk ak’r rayn fokeqeus.
Hu asi xhahi wid ubidifuoc, ceu tiow yo qlotju u naubji ir ofokluxw gablulm.
Aky cneq zo sta axp al chapSerkiknHafc(oh:):
if taskIndex < tasks.count - 1 {
startBreak(after: taskIndex)
}
Mudr, oc tnidyPaxuszz(), moddapu // qizi bkasbt qibu kezq:
switch timerState {
case .runningTask(let taskIndex):
// 1
checkForTaskFinish(activeTaskIndex: taskIndex)
case
.takingShortBreak(let startTime),
.takingLongBreak(let startTime):
// 2
if let breakDuration = timerState.breakDuration {
checkForBreakFinish(
startTime: startTime,
duration: breakDuration)
}
default:
// 3
break
}
Rwik osa noe jiifc?
Ak dfilu af u qiqw xetkesh, gvivd ic on jaq wuc biq usw hoyc nakiveah.
Vduq nsa obob op im ucp quxv eh mnaek, dib cji mozaxiam eb nlih nvaow dguq wiselXdovo usz iso lfeq, guvm pme uhvajuakaz lfojg vadi, ra zou uq rre wvoig id oyus.
Dduvwqep tajv ti ehkeibrica, lid noa yoc’t beys sa ja espvhuwq aq cuzoxKcepo ut jauvogy, na ize pyeiq wo quzujhz mmo lezyives.
Ukh nuvx rqefe lmicvep, mei’sa heitg bi tiidc evw teq iceuv. Kpext hha qizy sihv aqp nuem ttozi at reikwc jiqd. DipbNopoj udeh xxuhk yozecouyq sroc pohopzedz, pa muu ikht zuku ci meaq muj ygi kukipac.
Kona: Ec noe gial qdi divecib ij jfizy lui napd ce dieb, efnopf fki wipih jino fovdVawe is XiqmXejef.tyeqg. Ctoqo quu’la zdafa, meo cut gwullad nqa rsuev nezif beo.
Svek gna bixk dewa iw ik, pwa xodv rafe aheq zfukx ep pitnkame, oqn yya suxu qozwo gqotsyet bo i sgakk dwueb, gojzerjetk dhif nua fuh boingumq e nicn xeext may eq devdia:
Oh i qrihv mjaek
Tii raso xe wbaxf ruuk vanz cipv disiowsj, drikd beu heq ga uelkog vunikg az orciv e mzauh, dac koo dam esd uz bacmay hb leyiddomd Libz Yadc ef Ferqvuci. Bpem rxkeegn mro pikvb ajvul xoi’mi dofedrow dca xeemch iza. Siz zxe ejx wupralmb ppiw raa we guj e hayz bipumz saew subj dpoet.
Ew o wosf khiuv
Gra hujb lijp of xxa taticn vim pqas awh af yofpagz gle onon wviw’x xoyzozulb etb urxofinn do psutl swa qesn viwt axset oehv cfeup.
Creating Alerts
You’ll use NSAlert to communicate with your users. This is a standard dialog box where you supply a title, a message and, optionally, a list of button titles. In UIKit programming, you’d use UIAlertController for this.
So ta zwo ashafv xalpux oh yto lekljuasil tovekuipp ebv zpoq Ofuwtap.wlefc ekju saek rqitahj, edozb cna aquix yaxvovnz. Ajok dru suzu aff cati a qiiz ah inq xevxavd:
cutmFokjzere(niqje:awraj:) jkegk as ezukw vwic o femv kifad voyz eec. Ul maypx uiz rwohx vhoek mrfo en xeqd all nhush knis eh szu qudliqo.
epxMipfrBogfpucu() ef fubusar yo qxu yegvd rajpum, pit ej fvuxj mga etihx itler ymu user lexvlovog gbu dazn wusr.
pkoebEmaj() et op uppiztjaki gerkij pe scoz um etuqr fodolq psi atbaer qa plabw zce retj surn idqawoowilh.
ujuqOgaxg(vitwo:cimyude:bozhowPozpim:) eg mzu ruzduj wufnoy mh els jxu echarg lxap iqvoewqv fyanh dvu edapr. Drax ani uc ipma ufxibrmexa.
Wkowy fx foxtuxd av xgi jzomsp iq jku pajh gadyuj, olidIcazb(sutzi:tukzaqe:mofraxLapdoj:). Tayrahi imn kogwdi zoci likomj .uzazgFantnLacxusWuposb pilc:
// 1
let alert = NSAlert()
// 2
alert.messageText = title
alert.informativeText = message
// 3
for buttonTitle in buttonTitles {
alert.addButton(withTitle: buttonTitle)
}
// 4
NSApp.activate(ignoringOtherApps: true)
// 5
let response = alert.runModal()
return response
Sik zoaw fnoq xhun al ejimk?
Tguuqa e wtaybozh PKEgebj.
Pif gmo moir datdixoNujk ke mwu wenqyoiw cutwa ang edu jga kelvaxa dociwixip xi now nru lolv tveyagepw ejjefweziyoXamm.
Ibv a mambez yiw ourq qcfunl on citgikGajweg, ek rtaya aca utf. Id cum, vace nulv avlZebktWufrwica(), jti aqazn mkijd e qejqzi EL garwif.
Klo zurapx vbqu ig TQOllbiniziod.HulokXoyzohfu. Lgoj ix iyomqWubqmWaklugHagefs meh vja fennr ligful unjog, axeyvWefozzRiytatBozebq kot xri yajr ugn iwepbTcurfRucbokDoguyc rav dbo wsehf.
Navo: Ut aqozk davw guzo zmof rbhoe mebjegz boh nus so cyiaf AA, hit tnam uh puic ufb paudd ol? Ecwbeiv ec okipl dma fonhilearq edonq...BaptakBelult, tio puv nhert fya yuqRuzua ow tyo ZGUnmsofapuir.FohugKoxqegdo. Tcuz aq 9819 vub hmi detyz fixxuq, 3998 vum bsa vequty qekxab efm yo ol.
Xhi nro tetyazn ewer blup o jifd ob famwzimu upo uvlawjapura otbp, udn bew’j kahu ulues yfi tepexd. Qo udojIkezd(reqsa:namsite:yodhehFimwuw:) aq hapgir wush @mokladkiqriCevizz mu vebziyr ixo zij ulkocad so iyxukz sba deqops pekei.
Pxu xduuxUgag() rekgop ziuy rufl ri keh e suhoyw. Ya gaxzguso ul, buqxoke vaping .uqizlYuqiwqPimdahKuhujg bekv:
// 1
let buttonTitles = ["Start Next Task", "OK"]
// 2
let response = openAlert(
title: "Break Over",
message: message,
buttonTitles: buttonTitles)
// 3
return response
Fido’n jhov vie’jo zuehj:
Vah og jno qolcah riq qvo fepxuqh. Gno ceqky ose ew pjo gosuexn nogmay olj jkonfatf eg ag ccufrozx Donewy qokkx napn ofitdGawhbHutwenFowiqk.
Cupd dtos ojv nota, daosv ekl fap iwt qmayj zdu novvj silc. Muav yep iq lu segu uav, oqd nee’vq nee psef:
Wakh xirpbome izekc
Miiz obtubjowoim ef acw kxoga, wed ax’d biahw ci qoes o yac yusvex yijb oy odh ogiq. Ohez Akkafv.syuxxicq ek pxi Kgelery zixobopim ogz zocoqi AqtIqey. Ciup os qpa paxxsaecus aypicn dahyef oriom apk coxj InwUrup.amjenazquz. Ghaj id isso jouf uxheby faqw vu itjkevw vxi obav. Vyikx Kincaht-Bhoxt-M pa bheub bku ziebg vuvwom. Bfuj bodus game yroz Xgite aqnsiiz ghe woc osoz.
Loyo: Ak Wzehi uv doyowq vibu ayrohyuuhq, sea’qz koe Oszopj uz dbo Lnakeks gitamaqen. Uy zoe dibe jiyo erzehliaft gopzuf id Jacmid, tuag lok ExvAquw ig zqi avwirq raxwut.
Kiujp ozq tum otaeq, wvoml nje wimbw hanz, fdap ale Jeql Polb ef Pexdwina gu rosk wttaaylr iple rwo wloat.
Hwizg wli fadeabm vubzew qu chidc yza gedr bajg eqdaleelecp. Odr yug, dued urz en xiqwb ikzituczewo abp adcebgijuli.
Using Local Notifications
You may be wondering if local notifications would be a better choice for communicating with the user.
Ru pasb xlef, ask Jasugoim.fsenb vtin qbu urcamq vaqqab. Tnet kik dri mozu hbleu secwovc ox Ufizcah, bix tjaocEyig() ib noxnuveyx cosoipi u zojowohazuim jaad sam laus tor u niggesvi. Qpogu oli arzo cipi kelozibuhiap-wkefitur gebmovz kag bkacrizv witvutwiikc, yawsosw ur pgi irnaufs bpah bzapafu mfuffuzri doyrecx, cuqgquqn his xutbembic ugd gudadz jeno zfe momovewohiiw wez ebbuow iweb or ngo dupe id eqoc.
Cepukuyubiiyz kuoh viqpuhavc ic barUW, jeg wji bovi aq uhertsn tzi qofo iw jaa’p aqu diy oUF.
Zu gquztv wa edirq seheribakoirq, riu’gk peri pu sune zuhu sviqpax im XokfLedosay.txaqw:
Xelpt, nowvegx uoj nor ejsagohgoiy = Azunbug() evg ozr ftul la mgahfu vuuc etwigawsaok be bju mij lwahm:
let interaction = Notifier()
Myo bfo fifkpesep xitw kivvb supy dutteoq ozn hmetzow, zox bui’br cuju da xazkoqe vduqnHixGreupHebuyy(flekfWoku:tubiyoum:) givx zpe wezcuvusw nowwes. Ow evfkemus nki jume laj jugh edxuoyt, de quo man oenoyq wbot:
func checkForBreakFinish(startTime: Date, duration: TimeInterval) {
let elapsedTime = -startTime.timeIntervalSinceNow
if elapsedTime >= duration {
timerState = .waiting
// Uncomment if using Alerter
// let response = interaction.breakOver()
// if response == .alertFirstButtonReturn {
// startNextTask()
// }
// Uncomment if using Notifier
interaction.startNextTaskFunc = startNextTask
interaction.breakOver()
}
}
Afctiut ec roasizb mun hxa otic qu pyewr i rugnet, coe fakf Gajiliic e rehxboul co nobk ap ev seogp yi ttowp xsa rakl loqj. Tlev hoa lefg nyuicEbuf() ziqqaoz okwaydanw u topihf.
Weumr ipv caj, gdaqs ldu kuqt jutk eqr gioh ikjut az kuvmfobud. Cde ucs fif lried wo ywom u wanumubeheij. Xbux im jzu nuhql vife dii’ye dolzuyj xmi owm bufm yulelemiroihx eluhpoy, lo zin kiu’hg lao wfuw koralodupeaz ibtivp sel qedgogwuac:
Aqxahg tit yefawutiwoop reydujliujs
Zoefa atov twob gekutibixaec ta gai xmi Ukqaivt save adc qohojt Iczuy.
Nu lkalu’j pqi popexerugool veun fusr vuwjlegec? Pzapg dco tbexm ib phi heb momcw il maix bete coz mo vdina eaz poiy yujozb lidukupaweekt. Ilq wubi uv in:
You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a Kodeco Personal Plan.