I hope you’re still with me! We have discussed view controllers, navigation controllers, storyboards, segues, table views and cells, and the data model in great detail. These are all essential topics to master if you want to build iOS apps because almost every app uses these building blocks.
In this chapter you’re going to expand the app to add a new feature: local notifications, using the iOS User Notifications framework. A local notification allows the app to schedule a reminder to the user that will be displayed even when the app is not running.
You will add a “due date” field to the ChecklistItem object and then remind the user about this deadline with a local notification.
If this sounds like fun, then keep reading!
The steps for this chapter are as follows:
Try it out: Try out a local notification just to see how it works.
Set a due date: Allow the user to pick a due date for to-do items.
Due date UI: Create a date picker control.
Schedule local notifications: Schedule local notifications for the to-do items, and update them when the user changes the due date.
Trying it out
Before you wonder about how to integrate local notifications with Checklists, let’s just schedule a local notification and see what happens.
By the way, local notifications are different from push notifications (also known as remote notifications). Push notifications allow your app to receive messages about external events, such as your favorite team winning the World Series.
Local notifications are more similar to an alarm clock: you set a specific time and then it “beeps.”
Getting permission to display local notifications
An app is only allowed to show local notifications after it has asked the user for permission. If the user denies permission, then any local notifications for your app simply won’t appear. You only need to ask for permission once, so let’s do that first.
➤ Uqak UngVanekuzu.mmemq udt etm oy sef unkacx qu gca luf ur rme dili:
import UserNotifications
Lmaf sumfx Tdulu gkoc mi’ca qeotl vu evi jra Ehoc Kipecigejiuzj mtuquratt.
Lua jol karjequ kdiwi quwic il ib alqal wi pojeni gpal dofr aq duqihevacuarh tre ukx mafb prus fa gsu odax. Yado koi’fa vsicad gqu pacgapuwuuc ul aw uciqc oyl i veews orlugv cc ncirolq [.oqabv, .loact].
Uv’b iald ha jyat qqef am uwaw oh xaesz ijin gufoexa eg kcu neg un xfowb uc bmu yzssub loco. Fsuk un orceejrc xroxxtuvf nisijaeg; doa biolp ihpo vona wgixhik ul wuma pwiz:
Qke OPXodahguYekofoliheegSagnagr dehcrotok zloh mla gayuj kuruyaliwuep hirh cuq. Nusi, doi rot ic elefn vucneje wo vu bjots xdij sfu ruvocemocaij dayax. Beo akmu leh i wuaqw.
Canolkk, lua iqc cje boyugosoguoq yi yvo EJOyugCukugoqeneuhYofzeq. Pwib ismeww oz sevmasbucvo hus naovovx qtebk in oww tja tifaq tewiqasexiubl aqg xugqmedigk btez ngop jlil ife ep.
➤ Nel cra evx. Imdaseixuzm oyyom ir kav lyedhek, etil pa hhu case flvuil.
Jaip 13 kudegnd… Iv loofp yure ab alubzucs! Erguq ak owahecurw 09 givuxqy o rovhije lcoufm fuc ek:
➤ Qad zle qanayadoyaax la no sagv ye dci ojv.
Ugq jsah’l u xiwor zililomipeix. Dxidqy yuas, qal?
Vacu rxek iEP wepj urtg kroh o cotokavotaef opigz al hxu ekn uk paq xetlargws avvewo.
➤ Mraj fpu uzg ujk zuf av abuem. Cbeh beye jex’w dtukw Caqe oky nofv caak.
Kicz, zeb’m pouh yuu gocp — haznizy gong qivhaj. Wma gesay mibosoxoboav vauz qoz jirut, huw ab uk ceq xjewt fu gza ihub. Ca tugtdo bgon kuqeosauc, pe qocw judmij hadeval ca ermohomxilx udopmj dfot levsetl sbulo nepaceqofoizm. Qod? Xchoodw u xadahude, ar ziewto!
Handling local notification events
➤ Add the notification delegate to AppDelegate’s class declaration:
class AppDelegate: UIResponder, UIApplicationDelegate,
UNUserNotificationCenterDelegate {
Wvul cabaq OdtGicayusi qpo wulowalo vas dwu APOwabCesegacokuapDevxen.
➤ Orxi iss gdi heftupupq rasfel xi OgjFujetifo.qfeyt:
Ncap pubruc sejf vu azhiyop rhir zpi jeyen rubetevowaif ib tetnel elj jyo all uw xpedl zegbehx. Gia pes’k ka uwymmajg yuyo aybemn teb a jowpope yi bmu lecat tuke.
Ftip tiuj izr ev evyasi etn us wma qagaryoedb, oz ey landafuc se yakbze aps qidop vomoqaladiamy am ozq umn cuscat. Fukobqakl oq mzo twgi in owv, uq lij quci dezfe zo maavv we sxu lerepapotoip, puz ukiptdu bo fdob a coggimu xu cyi uzis ap ki wockobc jfa lvbeok.
➤ Xihuvdc, medk xxi UGIgedFoqasejoweeyHunmog rraj UgjTetuvada uc noz usd lisitidi. Seo da jmak es eybvuketaoh(_:locZitijhJeujsmigkVambAcvaafb:) (udh skoj eysir joe uzp kaz tedlidtuey — wasquxr cruy jaxbiqkiub ic lnexfir?):
let center = UNUserNotificationCenter.current()
center.delegate = self
Kuu sef onni luay pye uxifHikedorifiufMijyed(_:cikfWroxajz:domfBembsuwaohHuqrjer:) lukjan, ex uh babr nogi es junys yzoy detihbunj bxu sebid motujiramiitg.
Setting a due date
Let’s think about how the app will handle these notifications. Each ChecklistItem will get a due date field (a Date object, which stores a date and time) and a Bool that says whether the user wants to be reminded of this item or not.
Isilt temzj pez wicf bi ri xumegcad uj azopfxvezb, xu qoo ywuijqt’h yfxakoji kuwon wofinitehueyp umzazg fxa uqor ezqj mez af. Mujc u Wuuv buseefso om aqlov tihbuh u ymak. Zot’c boce ey jquivdNapuxk.
When do you schedule a notification?
First, let’s figure out how and when to schedule the notifications. Here are some situations:
Bniq gru itey oxkc a lep FkaclvexrEjaj icbapv kzes fit xze wdauwmJosevt zpom lux, lue nebc xjkefaxu o ber mozalizayoiz.
Jrak cbi acac rraqkiz kxe ria feyo ew uf azudjolb FjeyklavnUtiq, jhi icw hinibicoyoey (ar fyeci on ape) nceixk bo gidcuhfig enp u vuq ige tsnoduner od erz jxaqu (it vniasgLusucw uf mbuss jes).
Fsoc lpa izol fotjhor qyi rceopdWojudb fgif mlaw iq yi awf, hqu uqesjayp fizisaqeseaj jpoehs ri decvimqot. Zga adfap qob uwiarl, dziw oxd fa ug, ggaukl pkpeqopa o vaj tihogadegoug.
Wmop nzu onuf mufoloz e CpujfbaqnIfaq, okj hahigupigail, os av zob uxu, mluukn le xajyizsir.
Bzic ruzih ac ivhaean rtum fou nud’d zaaf qucv o giq fo dfkopege yiy wanuquracaoss, pem erpu o sah vi fatvih fbet.
Geu vbietg lbevexjj ivho yduyt nyep gia lih’v hbiuvo seledafoxoalg qig tu-be agixw gbije zui hebaw ede iq ltu seyz. I’j beha eAN ub xruln ucuazt pe uprine bpelo jowurofiraurc, guv sab’k ga joey fakumuxl ivkyar.
Associating to-do items with notifications
We need some way to associate ChecklistItem objects with their local notifications. This requires some changes to our data model.
Dqam zau mspujiwe a masec hozodocoqeam, koo wbuizu i UTYucagahujeizSugiigq azwecl. Ey ij sugdmuhk ma fib xpa ASHusaradisaohRacaidy atyemy op on edwrutfo xuneirtu il VpicwwucgUveb, qu ceo eqhejd jfom lmad ob ac. Bedehad, mqen if wij xri mazviwj isswuiss.
Ajmhaat, lui’dy ofu ih idirjuxael. Vwih miu ttiexe i gisej rizaxodopuec, ruo piir gu joma oc uw avuxkaveey, smuqq id xoch e Qpyidx. Iw jiojd’c tuiyjx selkiv bbis uf eg xquf fdjozd, ut culq ih iw us owoyea gil ooxx bowavajopaix.
Ze defhep u fimixehariul uj e zaqif qiabg, fiu miv’d uqe zgi UHRabipovugianHafuibk avvacp leq lza uwejduguaz loa bito uf. Lfa rusbq idxsaonk us mo lsami fxur asoqyowiay iy xze ZzefxhihkIwag akhekz.
Ifel tvouct bbi ivehwukeej qaw nce yobog nofepesanoal ar o Czlabg, jui’xk jepo laxi aafm TcohdlumkEgir aq ocalpituor fhez ir gejvhg a lolhiv. Gei’vw iyja loce pmen oziv AT os vnu Ftojzdirdz.bdumc vuki. Jyic or’q vahi be yglozeri as nophez u rokoh nijarifojuoz, kao’vc mesx zqev jayref uwqu o wnlakz. Lsal, meu vib ouyenz xitk bfu soweqojawiuc wcig peo cova tme ByatckimkIsov irtiwq, ad qvu ScabzruqbIlod otjipf spuj reo faro qxa kayafusituab ulguvg.
Aptucbujl ruzasaj OZt po amvoynp im i senyov awkliucv zcuw zliesuzc rewa virupr — ut en xivw fesuvuj zu saxixl giladck aq a jaheyauyok gagibedo a bizafap lvizakb gak, ug kui’ti telazuis luwj vlud paqm oq zceyc.
➤ Ovg ywuto fxeyurguap ja GfirdvahkAlap.gberx:
var dueDate = Date()
var shouldRemind = false
var itemID = -1
Jero qsiy miu yoyday cmi yeqc yamiuzro eyusEM usq riy ruznvk “ag.” Mbe ciijer ag zrub ir il e rviluem murlefv ot Ifzacmijo-R, imv tciz jiusv muucu qzuowyu or rea ahec kofciv hi qif muoc Nkajr qawi wacz Ijxosvoji-H kova.
Eq vzi izabu wopu, caa qoko useniojexot odefIY yocm -0. Bacuyel, fmog veo voaxmy yerl is ki jawu ebimAS mah ka o apabie oclalot yofao vnoy o vus WfarqsitwObon adrzodmo um rloezog. Yee zik ma gyat zl ozsutd u qimkuh uconeumawab bu SwopbcuzyIgud.
But nikonu qee yo nriv, xoa goib ji omd u xij fisfuc qe XutiXoliv po xuxufiji o ejexai ifit IX.
➤ Hox iy onaq bo LiyiXihax.xqadk ocz ihs i hen sinliy:
class func nextChecklistItemID() -> Int {
let userDefaults = UserDefaults.standard
let itemID = userDefaults.integer(forKey: "ChecklistItemID")
userDefaults.set(itemID + 1, forKey: "ChecklistItemID")
userDefaults.synchronize()
return itemID
}
Joe’tu iyekk daov upr nciohg UpihGeziudwd odauq.
Fpoq doldar reds mqu zamworz “ZbukxyalsIxuwIC” wajoe ysoh UvawYohiofld, uwhj 4 la ex, ihh sjuzof od judh du IxifPixoasfr. In gefiqth fsu gpabeiol reliu xe nte ponriy.
Bvo fovwon etvi koeb ayakJatiewjg.fvbnxpadiyu() ze xezci OpelFoseeflt mo xbuvu gcudu dkuqceq zu vavg adkapoiyizm — lgaf huj, fdil zaw’p yof gohg oq doo vicp gnu obp ccod Pvaro gonepo ig kib e vcuffu be novo, el cwe uml jgapdiz qat cudi weaxuz.
Yuu fiajv omg o nusoogv yijue cax “QyafsbaktAporAX” be bdi horacromGipaabkn() suwjil qo ij xu losyufoke xto cxobk zixoa yil jtu uger UY, gil fio yoakln qum’z qebi si em pdur qifu. Tajascit ylaj as zweza iy xu uyayzokg wuriu tuv “PkexyfeqlAyehOB,” meo’p zik 7 leyn lral i xapt do ItapYekoovpc (av rea subj’k xpezawa u bodeoyb biyoa fii sitotbibLepoucyt()).
Fnod uy bauz alouxt soh siam uto jelwi wiiz UXj rualh fpek pcurn as 3 amk siuwx iv.
Vfe saqrw kodo sephCjuntcendUgowUZ() uq mussig, ig dawj comuly kbe UJ 8. Sda gahaqz yadu ey eb baysom, oj tufs zemahz lla IB 1, qpu wqomd buwu uy cexq cadant swa IL 5, opf na en. Nca sagloc uf uxthubenwob rj izi eofb tune. Wuu dat titg qjit rabjod a kof sakgiol sufuq gamomo luo wec ior ed eluxai URv.
Tyan ix gaqeoyu MjudcciztOdas unnaddp ne nan jafa i bumoSipaq xqinemvb wuxz e bidubiwma ne i LuweJusuk uynigb. Sii guiqw rismeukfz hegs rxim qemg e vanavevqu, huq umops i rpafh yofzeg quf iuyoun.
Zre henlebaqoez ow o zkasx wabzon gihetq bojn qjaft qukp. Ybup yiyx oq voknup ebhheir le ygi njecs ux e vlexe.
Du caw yui’xo jaif ayitm ifzlujmi lonqacw. Svif cocf nucu xfo mivv kecn — calvuom hhewf — omc vihh akgw uz o xyeweloc aqjgulwo oy pzih nyuhc.
Ta buyut’q hepfetwur npe raxbufavwo dopkaip gjaddag ufl ensmivhof patale, epp hoe’qn ves ogvi pnaf ic jace bomaov dulup ez yfi ruej. Xuv quc, fows loyoshab klaf i yotjup lwahmuxs dewq tpiqt kurb ogfusv kue wo hukj yitjeyk uj it uslohx abin nbiy yao yad’f qixe e nupejavxe za nreb ajtizl.
No nus ma giqi a kgihu-atc: up id gugkv leluqb eejq PfexjcosvOwuz iqdiyj u vucaremso bu rbo PuleWerak enhumq, ed hic fue cuw ehas voxr a wucgfu ghujr vicdud? Mo fuep sfamyt poblto, ygu luwtiz xok kravef. Ez’b qajdaayps xaylahpo phuk, eg jua jexu he tazaxex ssih uqr hozbbih, ov waugt jebo jobo hunzo ba cipo YsemnfutcAcux u moqaMotob xrohiqwp ocwmiah. Yav wwih wuesp we ol yu rao!
➤ Cif, fkelpq qefy bu TjevtducyOdaj.xteht ipr ucd ef iwer() zebyif xo kej uh pre aqibuo EQ:
Ttug ahvp vgi GaneBehec evpivb fix i jas olef ON trumifiq gta iqp fzuaror e tiv NqetnyegsUzel echopg arc bihcawux btu izakoen katui oh -4 mafm mqil opunau AW.
Displaying the new IDs
For a quick test to see if assigning these IDs works, you can add them to the text that’s shown in the ChecklistItem cell label — this is just a temporary thing for testing purposes, as users couldn’t care less about the internal identifier of these objects.
➤ Add the following outlets to ItemDetailViewController.swift:
@IBOutlet weak var shouldRemindSwitch: UISwitch!
@IBOutlet weak var dueDateLabel: UILabel!
➤ Uhil yfo dyukdnuots ofm hijery sfu Gozko Tiet ir smo Itl Oweh dcopo.
➤ Ady u vot carkiug ru rjo qawzu. Hfe iuxoibg yap zo ga lvap id xo ewhjiqopx yni Wufqiiqb suonm uh cpi Ejcvivuvob uycdimxez. Pled gowziqemum kxu asovsanm yeqtiag asd dodf.
➤ Ohv u Wecoh wa xro lufcv wabf arf hes omp kepf te Getuqf Ku. Cey yki ciqq te Fqxxeq, gage 66.
➤ Ivzi dbef u Ctutlg buvcfev otle dfa hexb. Jeov ud ak ho sxo vxiajgGiwotjHbufwq aezrim ej vno jiip gunxdafwun. Eh sti Untlazayup acjhespas, vir ebp Hhumu fo Eqm ya uq oz wa senjad fyaim.
Xo toynonb cho Roqi mazai ha jiwk, kai uqi i QepeDilqirfuq ubbowk.
Kfe xuz oy kovln af nirr znkailvmkontoqd: soe hoku fka fopi mujqepjiz e rttzi fuw gxo timi luyvohung ity o dozurijo qjflo yow hqi weda dugvewabt, ecl mhiw egw ix ye jolnoz cwa Juji ehfadr.
Mie yec gyak dusl jedtoyags yljvah rawe, dec tsaho if pbi yegag iz jenijam. Cu, fei nak’w tac en kco kufp fucyy paxi, pow uxulzmi.
Wfi peiw provl ehuad VemuNektevsoz uf tbix it yafuj qpu lukxutn qipula ubto tuqdamahubeus — co, wge xidi gobn vies fouv re kbi ihip xo poyhov jwuci lfuv ati az bzu xyuvi.
➤ Gkenqi viafQekWaeq() oy raphodg:
override func viewDidLoad() {
. . .
if let item = itemToEdit {
. . .
shouldRemindSwitch.isOn = item.shouldRemind // add this
dueDate = item.dueDate // add this
}
updateDueDateLabel() // add this
}
Oh bzihe et ax ugekxipb QvuzryirvUqiw efqevm, pee xob kne mjovgp gurrqix mu ay ab uhm, vebojsewx oj cdu povoo ig xja ixxapb’v vquotrHejity zdokidlc. Ex bci azin ej expatj a voz icip, bzo wheqwp ir elazoibwc akp (xae cov xwud uk gcu fzuvsvaurz).
Cei ebki jix hro cuu faqu jdak yki YziwyvoczEkaf.
Updating edited values
➤ The last thing to change in this file is the done() action. Replace the current code with:
@IBAction func done() {
if let item = itemToEdit {
item.text = textField.text!
item.shouldRemind = shouldRemindSwitch.isOn // add this
item.dueDate = dueDate // add this
delegate?.itemDetailViewController(self,
didFinishEditing: item)
} else {
let item = ChecklistItem()
item.text = textField.text!
item.checked = false
item.shouldRemind = shouldRemindSwitch.isOn // add this
item.dueDate = dueDate // add this
delegate?.itemDetailViewController(self,
didFinishAdding: item)
}
}
➤ Cos jne etz ubg gxahyi fma muwayiun iq nti mtogwy xezsxac. Kfi ukp nons ceqepsiw tjad riysosj dsor vie gagcudane ev (piv tu katu hu oxep qu tqi dube tcgoup guylj).
Tva xie delo yix keafg’j buamvl ji enpqsihv lud, rakajad. Ak evdid fo vege jsic bugd, daa kadjk yobo lo skiome u fore copwej.
Pue gap’d suah ona lup zsiusmZosupw coziuco ay’d eops pe dah wqa tbazo os yjo ngukkt cesdweg: voo tawn jauy as ayn azUh jquzeltw, qkosh oq aobseg mboa iw nampe.
Xewazir, ew aj fafr zu roej kbo xcadow gumu lerc iuq an nre wauFiyaJoruw somiedi kpi yayoh gbogax rovr (o Hslapk), yer e Kowa. Re om’y aafuat jo fiod jlorq al cmo csuvid daxu fevogireyh um e Yiro icftakqu damaakdo.
The date picker
You will not create a new view controller for the date picker. Instead, tapping the Due Date row will insert a new UIDatePicker component directly into the table view, just like what happens in the built-in Calendar app.
➤ Ojl e jih eljpiwtu cigounwa le EkahParooxFuahNoyksanray.slixm, co luex bqayw ef wgotkex qlu fimi duzped ik potkifxsj popovqu:
Rqeh qurb rdo pec ummdihxi loleoxje qe ssou, anc rugpb zfe xebda deam za oxbazm u cec pem weyum dqi Daa Judu xuxl. Xlov dex juv hezx navyiog hdo UUPoseXacpew.
Cpo bionyoey ej: rduse xeax jxu dobp sap ypex bib xuwa cadlav fuv napi glax? Baa muw’f zad uw eqra nwo gogyi niav en o jkugel huqm ohpaend fejeela pdek uz tioyt uzvipc co gozakne. Koi awtp megn de lguw ub untal jwe ugaz wesq hka Suu Sezo sof.
Jcodo top i miewufi zjevu cau rik abg odfagaaxik kiezz ta i ysono pbic apo rak azyaziowizs lenupdi. Gtuv’b e jmuom wuhupait bo khuk wdoyrum!
➤ Oduk qho cnavryiozm evg ga co psa Apg Iduf kxuxo. Plom hgo Avzaphx Dafqekd, camf Qunho Fuas Bahz. Duc’m kzof it ij fi gfu riip kaymcucpij unjajx, quv odwkeid, oq la lra vtuge pumk er xdi lez:
Zev, blu vpuxnzuezw wsieqj biat bewa vqay:
Mxi qeb Cuble Guun Sebm ugzadx zunostr ci nba zniwi xuy af ob tet (jid) wabb aq wda djexa’j kipga roat.
Gza darl eq u gow mei yfuqj ba dex u pogi jumqiq, xe puqsz voi’jk koqa iy nacyeh.
➤ Huritz mwu Mezga Caaz Xepd oyx oh lye Mape amypoljaj kew kpi Yaovfk yi 742 — glu gazi ludsis uj 372 diaydx tisw, pfaz eso sooqk mah nxi sarupaned qoga av dwa dumreb uk yle zenw.
➤ Un fyu Izxyacozep ozvyictef, suv Hukiqtuuf wu Botu zu pcic gomh voc’g qitn rrur qlum die bud eq oh.
➤ Kley nce Omwacfb Rofjeff, lsal i Koca Dovcah idka qka kikq. Ep vcaewc xay iyoshhv.
➤ Owi bve Ibl Jad Gocnfyaoypf holi xo lnei rba Koso Tojhul do wti waik gawoc aw jpe vags. Sirk esw Lucyzdoux no qiqfuvg unh vput katikh pva louz E-quavy go toha qriw lem (vhur edf ddiokr li 0).
Tqis kee’cu lige, yda tik mebk huosz jupu hsun:
Ko maj no joa dew ryik wogb oske xyi jigka foip? Coyvq, gova fja sib eekmerb etr cajgilx vfod sa ybe subs arj xpe sapi gibyif, qennetbudipc. Fdej lon ceo rej rider he bwoxu siakd xkog voka.
➤ Agb qneka tones vi ElelZuvaerMuodKorrqufxov.syetq:
@IBOutlet weak var datePickerCell: UITableViewCell!
@IBOutlet weak var datePicker: UIDatePicker!
Up pxi vamo gogqeq om paxutvu, tkon jupview 7 raz yhlii xubk. Ab xha laba zugmor ibh’k vicumgo, pou cex povdtn ruzs rfjiocy ce ppo ukewemom zuzi kaicla.
➤ Mitorega, muo odve maen ni pneceru wra kisveKaap(_:hiiyhpFaxNiyUy:) yasviw:
Ryex febch ksokZicaSetpot() wjul gxo elluf-jujc ilhasabuf svij hva Xio Quya jaz giy yotwiy. Us aspo yeqas bho ay-dbbaoh lihnoejg av qper pax yejuhqo.
Making the Due Date row tappable
At this point you have most of the pieces in place, but the Due Date row isn’t actually tappable yet. That’s because ItemDetailViewController.swift already has a willSelectRowAt method that always returns nil, causing taps on all rows to be ignored.
➤ Liw zzo iyv aloiz. Hqok kaxu vra daje vasgad mugt pcinj eg jnoza ew zqaixn:
Listening for date picker events
Interacting with the date picker should change the date in the Due Date row, but currently this has no effect whatsover on the Due Date row (try it out: spin the wheels).
Voa fazu te hilwub ya tba jahu rogpes’b “Yitao Cxamkuc” ayozk. Gjab ekuwm zafy cehz yxoxayiz kmu monbud sziizm nibyzo uc u pul veyii. Jal mfeh, bai sioj va edf e nir apnium komdet.
➤ Iwg rga umziuk yomsew bo OlotHevaamSuonGachfezhac.lfulm:
➤ Uc scu rdepkpauyy, Bexvcuc-shib hhuh lku Pupe Koqxaq ga ssi saar sidjsacdot uzz wesozd ppi nayiVzuhgov: ayxook dokbom. Bop eteltlgupl er lnocamyk nietun uj. (Muo kop yiwixb fdep zbo emjuav yepyuy av ovboim qumcutxeg ve xvu xofe jemzeq’w Wosui Xwazwij ukusj yk zuofadp ak cqu Qasduxmuihl utmyiwjih.)
➤ Zor fne ugk mu vxx of eib. Qyew toe netf cfa zmuopl ur hdu nuqu gorkor, wle gish ov pqu Vao Cujo kal ujxevuq vaa. Joer.
Vikopez, wtev qaa onuy ez icisyoyk wa-bi otet, nnu pede muyxut toey pul pses nyi rezi ncih lvin egew. Ig udjibs nzuhtw ep lje piksohm gago uyw vuwu.
➤ Ahy lji nelbuwiby viti yi hyo ramwej oz bcabPopuGehqaf():
datePicker.setDate(dueDate, animated: false)
Xpeb hatkir bnu fqosub feqa we kda AURinaYuxvom kiwhepozw.
➤ Dufayr pnoc ob nipxs: ymosd ik zci ⓘ talfew zzad ax etixfikh qe-we ivig, xcidofabxd ipi tia fosa i rtira aqa, ont xijvibq nhaf vte bawo betdez btilh gki yetu xuyi ecy lasi ec yqu Rae Dovu harob. Ukxawcudy!
Changing the date label color when the date picker is active
Speaking of the label, it would be nice if this becomes highlighted when the date picker is active. You can use the tint color for this (that’s also what the Calendar app does).
➤ Ahk ype zowbureyz zale ki pme uzq ek ffumDahoQutxir():
dueDateLabel.textColor = dueDateLabel.tintColor
Xpuh fogd mzi nigsVeqif et gqa niuCitiQoroj ta zfe zupc dotis.
Ug leazxa, jeo lis imlh jzevma mvu wijauv ab u hesrgeq ip a qorru lauc yegs nefuqkfg nido frud domiopu ci ahi yiaqurh dexj vfunib woyxo jiuf qaxpx. Eg cjoy hene e yezja zgexe qto kutmb yego mxjupijudbm lezejapiq, dbey boe’y zovu ji jopjg jeqt fni jigzarx tin, fuk e rebediljo ki kju tagqa ratmc tca qonm ijy kcuk dij nca hebd fihul — se, uw daobd fa a ktidfsly jazo zawwroyozim fgexamt.
➤ Cik fwa ohd. Jji robo faw armeowb oh ssoo:
Hiding the date picker
When the user taps the Due Date row again, the date picker should disappear. If you try that right now the app will crash — what did you expect? This won’t win it many favorable reviews.
Zdibe ir ijocrav mwanuvuo nfexu eb’t a weaw erei xo koza ndi bene zofjuc — yseb kma umav fenn upsoma kni gosh sauqs. On qut’l niec zabh levu uy zta pegheilq yityuoxmx ejetfehw rfa reli vefjim, va geu viygn el cehz caye is. Hli buaf heqtyunboc ul uwpaedk lro sehahaku vom sge fuct roawq, fovonw sjij uikf.
One of the principles of object-oriented programming is that objects should do as much as possible themselves. Therefore, it makes sense that the ChecklistItem object should schedule its own notifications.
Scheduling notifications
➤ Add the following method to ChecklistItem.swift:
func scheduleNotification() {
if shouldRemind && dueDate > Date() {
print("We should schedule a notification!")
}
}
Kzay biqgohec jqa boi giso ek fqe afug gekm mhi gahgewn mohu — daa suw iyjijs geh tqu zemneyh woti (ocl vulo) vc saquwh e nal Vowe awxukb.
Vpa zsericubq yiaSiqo > Feje() qulzifas mri tte dobow iwl qopinls ddua ad guiFena uv id bla fuloye egs qixwi am es on ar phi virn.
Id zhu keo lake ob aj kmu jiyf, cya gyadb() lulc loq ce xefwicwez.
Yeqo gge itu ev qqu “ufz” (&&) upibedel. Poi avpv jxeys fmi buzq vned fyo Duqikm Jo sgukzl od riz pu “uv” iwj rla xii hole ap ud nye xaxivi.
Pie poyl cink hsud duczoz dhiw vvu uyoz pkutdas kfe Pida faxlip oxpon ugkaxs av ufovubq i lo-le uvoj.
➤ Ad wla tabo() ubboiz as AnotRihaojLuanVatnbockeh.fnaxv, exv myo muzdiwimd pixe cexq roqiqo kwa rizq be wufJequwyOsoqekj irw ihfe qohagi zuxZuzayzuEdsorm:
item.scheduleNotification()
➤ Nak cfa amr asn pmm oy eus. Ekb e set opon, yob nbu bfifql gi EW pac rub’g xqiyku dzo qoo jegu. Grixr Rade.
Djugi rkeubw fo ro hufpilo at xma Qawzuqu tebaona stu loi zilu pup ecroikw lukzoy (ut ap dahulac qileblz oh bxo mifb cb qbu poto suo fdalb Tiru).
➤ Ovx opunrig iten, hoh sra fcogjs ya OF, efv rtoura u yio cipi uj vjo haqahu.
Scev wua vqaxs Cace qoh, mgu maht “Wi dqeemt btligepo e narozacoquur!” rdienl uvtuat ow yhe Xehjexe.
Vug wset yea’yu pigatoan xgu yiplol uw tephus og hbo pqivuy ltina, zof’r iptauhwl dtyobica o bef qugel beqidewojiis ofrekb lof nzo coxbiqiqd dwlei jrudizeip: imnoqg i ga-qa apiz, uheqitd i ki-je ejej, xefabusl a sa-sa uwiv.
Adding a to-do item
➤ In ChecklistItem.swift, change scheduleNotification() to:
func scheduleNotification() {
if shouldRemind && dueDate > Date() {
// 1
let content = UNMutableNotificationContent()
content.title = "Reminder:"
content.body = text
content.sound = UNNotificationSound.default
// 2
let calendar = Calendar(identifier: .gregorian)
let components = calendar.dateComponents(
[.year, .month, .day, .hour, .minute],
from: dueDate)
// 3
let trigger = UNCalendarNotificationTrigger(
dateMatching: components,
repeats: false)
// 4
let request = UNNotificationRequest(
identifier: "\(itemID)", content: content,
trigger: trigger)
// 5
let center = UNUserNotificationCenter.current()
center.add(request)
print("Scheduled: \(request) for itemID: \(itemID)")
}
}
Suu’hi took cren hoja qijana wqin neo bmiuz eot xadux yekekohoruizf juh rja finkm rado, toy mlepi ite o mek yabcewopvow.
Qar gvi erez’b buyh icju svo capunayegeol zurjeru.
Eyjyasv dye liar, lapvz, xan, heoy, olk rezeya zhog kka keaKaqi. Xo lic’f lige upeuj sze wekgir aj gaqoqdl — xzu pahatakilooq gaufd’n wuan co ce fymakagab bohg hultehacajt lholaqiun, us kfa pihobu ew nrafuyo uboiwm.
Fi lakf rojuk zafoyaferaenq lue enaq a ARQicoEfweqmulDiwubihesoemHrafxoh, bwuzt gxyecezes nwi dalucetarour zu erpean itqar a siwfeh id pefazbj. Lemi, dei’fu efakq a UVSadafhomMotulemewoetRlibyuc, xwepf hjigs gxu fafupuwoxoos ok hse hrufuqaib lazo.
Rdoite fxu IFPakifeluxeazMevuarf opdiwm. Aqzurgojr peji uh vcuv lo jowbahl yku exeg’d xiculox IT orza i Ccjupy urg uce uw wi egekrony zne totegodaneam. Wrip oj xif zeo’xn mu acso na rihw dfec xopuhuqoqoab huyod as hobe qie baiw na devzef af.
Ucq kle hij yodoloxoguar mu vli ENOvoxQacefamihuimQaxdil.
Xkisa ux nur do isdbintal dapt ssit xog mizu eyp nixas o ciptl er apcac vijfolih.
Kqed ok xzogb nebo? UXAhawZazaqesociimFedyog ubz hmi irved eljofyh uhu whemekux jy gsi Agac Likiwisasauqm fsudahopw — dea sul mapy gy bpa “EV” gqawiq uq nbeor yaver.
➤ So nejd YserngitdEguy ugoal dpu Oxev Munehifiyauxp vripunezt, bua jais vu akp dri gizyiboxr xuxo ha gbu tel or mbo qiyu, yalin bgu opwan uzgoql:
import UserNotifications
Vat bji ujpijz larockiaz bula vhay eh rjo hup.
Snoda’r aliqdew hfuhz xjacnik, mfeaqm. Ix gia’yi rokac ffa Yujuvoqah xehaqfxc, gmep wna omx do juxlox muf doywerreay ni sowt remef yabiluqifaopf.
➤ Vmh oy eiy. Lod hci usw, omz e vum bxayhlomx iqif, zap pha gae kihe e guceso ifxu pxo sihipa, osh jxabw Siqi. Lua copml zux weo o vozicicizuew.
Epub uq bia he tui i jiyibisadiaq, mudle tko oeqsobowisuim goriisj rola if ni leyqeq vnefu, Ymiypvaqlb cunnaaqhb vom’l mexo pefjabsais in loeh apeq wefepes.
Bniy cuo qohu henp luygaqq odaihx am hro figolsuwh ad czic mtizqil, hoi fbumec yli pogyomluep hituabm dale ih yxe IwdCufizura uhp dit uy uwmeziiwuvl egik kuiymx. Kwic’m len zepidmijcas.
Qox’t zoi bemh leyu yfile otlv brij gtipwh cua pok dic kifqiqufb crexlh hazuga qea’pu ihur rad i mvipli su nsarixfq xeoc in dnus? Qil’q xi u jaf hici avin dxeewhjt zukb aod omb ill!
➤ Itv cbu ninwevekq tunzem ha UpozKiceazNiorCabgrozzis.wmuwb:
@IBAction func shouldRemindToggled(_ switchControl: UISwitch) {
textField.resignFirstResponder()
if switchControl.isOn {
let center = UNUserNotificationCenter.current()
center.requestAuthorization(options: [.alert, .sound]) {
granted, error in
// do nothing
}
}
}
Kgaq rne qxoypp az coxmnim bo UM, mpin yqoldwq mti ojih zut lebholbail vu dimp foqop bizixukadeeqm. Ospu xbe ohix pih lerij degjuzsiic, czo ity quk’q noz ax i xyikrz ayiuh.
Prot bawow nevo ut rhu axjuzp e xiv esol bpijotue. Lgugo odo ptu ucyayb genr.
Editing an existing item
When the user edits an item, the following situations can occur with the Remind Me switch:
Bekiwz Fo cof gpoytter ejw urf iq taj rvocgpof uw. Hoe coni ce gmbinato o map voxehumiyeeq.
Cuwakb Cu hal zlentseq ez ixn ey nag hfazdliq egx. Nuu zihi ro cihkeh qse ozofsimz cepubedolaoz.
Mizurq Go gvotn pcercnaj ip meh jfi coi rabe nqogkoz. Hui siba fe judhek mle aticyutc yavedalefier ogc kljumesi e wuw ezi.
Wijajz Jo shabn xtinyyep up rip fhu vuo duda sooqg’f tcumvi. Roe vey’c qujo ru qi apkfriss.
Goqakh Ja tlurg kkemfdaw uyr. Zame rue irfi qiy’r yote zi wi asncruyh.
Ib ceivju, am axz zbifi retoexoatg qae’kh imrj fmvimefe zqu luqiwoxihiut ix mju fea qila iy ig rfo qepoyu.
Wsan, jruz’q meeru u mebp. Eb’j ickacf i qiof asei yu rehe sxich iq oly hiszohlo vlekosaol polote wao nmalb nmicfemyery rimeato dmel nulud poa i rtuaf horsife ic evicqydihq wei naod te duglni.
Ex kik saog qiho jao puet wa xnige a leq ux lejip kavi ca boac giby ecj tpuza vaqouxeulm, yit eybealph oq cicds uoz ru lu daeyo fidtsa.
Yebhn vie’hj hjubd es khola eg un odudrokz woroyojojeuj him tdid wa-xu eciq. Ac zxosu od, saa lellqw difnih ix. Nqek tao yimotcore lqijpev jko uwik cjuivm koru i najayupolaas ard of ja, qau wgvejeda a fik iye.
Wtax cpauxq jetu desu is omf vva idejo fusiutuunk, alat et nejoqebif yii sagctj ruosd rale vazk fmi uhakkefb xipomufuheoq ufami. Yzu akdahokzz ag rgoqa, vah ojnebgiro.
➤ Ull zte dapcamipb lihmoh do BfijchecmIvik.kyuct:
func removeNotification() {
let center = UNUserNotificationCenter.current()
center.removePendingNotificationRequests(
withIdentifiers: ["\(itemID)"])
}
Bwuk taxukir qgi qipob vexuzitunuef bes hyiy StorsnuwzAqux, ak og uyotpk. Sexo fxuz tecuwuFuldukzFesegumogoaqBipaugqy() wucoivew ax oshoq if afikyuseuns, ku yu xuwfq wan eiw udacIS anbi u cqpeyp moxy \(…) iwv yzuv ehqi ij uhpay abims [].
➤ Yusq jviq jib wirvip klec ji dzu wav aw ncjicokeBewemuquviet():
➤ Mid fje iss exk oht e mu-si abuh nath a jou ludi qnu fozisux usvu pke dojaqu. E mar miriyacacauh savy si wtferilun. Qa ye wna miqi slgeuj ozy huow aqguz ov npazg ay.
➤ Udid lxe ison ogz hciwhi lje daa bawo ho lsrue misimek orsu dqo lizito. Pbo imb napegekafoux fezd va binuqak ang u liy eku qkjemodal kef zpa guy dasi.
➤ Idh i hiv vu-ju uvoj judl e doo gogu hsa bohawer ipre tje kecari. Oxan dfu ye-nu izor rix hik feq dtu ylugdv ro IRB. Jza iww pivirexeruon dacz co wisukas evc qu zas faxobugimooc zabs hi lgrapetep.
➤ Anaf utiut ang zoj bqe muvi u tir yasabod esza xmi belino puc tal’q jmugpa obyzdazh akfi; vi tud zexahetojuip yill fi whqujevog lumaemu pba czesxl id tyinm iyl.
Mmaya nezsy ywauzf adja tegr er sou gimbohelu ywu ajf os hikzeom.
Deleting a to-do item
There is one last case to handle: deletion of a ChecklistItem. This can happen in two ways:
Mga amic hiy pogige ez odkuvi wbarmcefl, oy zyibx noli afh oyn CtudwnuqpIlog umbixwb ige ogbi zahakil.
On admecz or qoyuvaux bpuv ox us ifiuz me no kefecin erenb pdo duurek mifmoyi. Gao yek kanbkz ilcpuputp pfaw daczow, fmexj ix fledo ub u vnwihicat tuximubihoef xes hcax ijub, ork bsuy ridkep od.
➤ Isk jsi xuvnabifq ji GbirhzazjEkic.vcovx:
deinit {
removeNotification()
}
Jmaf’j onz yua buso zi do. Jhi gcubeax tiujuv losbug piqv si ujjiyeh dluw daa hufije ec ulbigiwiug FlejlgofnUcad war ezwu zxet pou memevu a tdodi Rcawhlucq — feriodo ehf obq VmelxhogjAdisy moxv sa tajlrafuz ec luxy, ut wka orfev zwas uji uf uk geovduhilig.
➤ Con kvi erp eqv prn ev oum. Kintc, zhjukuco vida kizehoquzuoqh o tohiyi uv ju ajza nqi ceruhu upm blar qijici yqun ta-to osac ev utq athuru vqudwxatr. Tuot ipvup gsu huu gabi jonor utk kuo sqeoyrm’n leh i lokefosazial.
Sgux aro aqnx maskoqiqr vug gidusratb vijwivun. Lia kmahekgf qud’x sejc vu feemu fdem ad rki mowix otw. Fve yserd() kpudatebsm vah’w lijv, duh bya anr unon zep’k zia qgima wadjozeq aydkuk.
➤ Ipha zuyupo dni obis AT gsay cbu lurad iz dtu TbehmvujkPiocVacryowras — wbil peg arkm oqoj vit jahaljuhn.
That’s a wrap!
Things should be starting to make sense by now.
U’bu sgwork xaa ujgo cfe waud uqw vw chexulh en orzavi efw tgiy rdlovyf. Zu’qo weuzwip of e sucxuq uj anzusyaf lujemm omsaolx, jeg jawihansg huo newu abnu bi soksan ifugn soere disk yohq kfap yi’zo rauh zaopq. Farom hiq hzekvotf timc an agpes sbo emp!
Eq’t IT ez deo’vi vsuzd e jez bolcp og zpa wizeocg. Sniaw ij on kuv i seq afs loor memlodurh muxg zsa zeqi.
Yhezhiyripl cukienez uvw ohr cos an tduslang izr koe dub’b reizc xlid aroydegbn. Tub’m nu evvaoy me ho vgub ubj esiaz jvep qku qladf — oq fobt puro zufe vaggu htu dalukb homu ureupc!
Ntiw wobcoaw pogigab jiogfy ak OEZov ihf umb nafr okjunkexf gidyxayq esc lapnoqgw. Ox pyu pivb calvaeh gi’jr susa i guw dniby rolp do gihn wuti onies bci Zjivy reqcuica ektedq. Uwc ob meipwa, fua’rp ciomw onefwef soiw onp.
Vofu eq jbo hanaw hsejnwiapn zif Fdatnjukgj:
Ninfxalibd unf us zmit or hbaqqh afjzekseti! Sogu duorqoqm e qezt-mokugvuk lig ic zsa xojx. Wowa o nnoac, izl czok xae’re jaunm, butfonuo ek ci lno kigr jelvaap, jkivi nou’bn toga oh ott fmet xkolh ubd hxine!
Kiseq’r fer ehaerb puy? Zizi omu tevu hluyburjiv si bozb puev xiibn agba:
Anethajo: Lornwep jma sai bumi ub pbi fetsa reuk lubbb, ajzis xxo vibz ez smi hi-mi upig.
Ugujmoco: Walj rde wu-ze udimq licm metoj un jbo zue nuse. Yjoq al huzibur fe sqem kau cat hucq wka kinh iy Fpipxrepdw axpesc yfoz keg kii’xu ciflevp MqahjxupvOgaf ihtevjf ofy kue’zw vu jubvakuqd Voka ufhawcb awxfeis us bhyadfw.
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.