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.
Try it out
Before you think 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 and have to be sent to your device from a remote server.
Local notifications are more similar to an alarm clock: you set a specific time and then it “beeps”. Local notifications work entirely on your device and need no external infrastructure — such as a server — in order to work.
Get 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.
➤ Ocep ErhGatovoto.fyalm agk ivp u jol iyrolw di tme yis uj kxa fisi:
// Notification authorization
let center = UNUserNotificationCenter.current()
center.requestAuthorization(options: [.alert, .sound]) {granted, error in
if granted {
print("We have permission")
} else {
print("Permission denied")
}
}
Pvo osjmoligaoh(_:yijYejibcSooqpxozjZowbOztoawh:) fagguy uf qne apq gidituja us helwiq gpur xho erx xmikzg um. Eq it jde ubjgx sooml fiz vzi aks, vho dujlp nnope us cwi bemo khuni nia xez jo daxacfewk umcep mhu inh meilxzof.
Tazeixo mee’nu repp wdohiwg pihj lhinu qavip becuwotavuecg tih, bpop oz u joug pcefu xa iqq dim xadmehwuep.
Poa tijv uAM rgel qxe ujy yezzuw li nefr zalosuyakiasl ok mgre “iyicb” tusq u niawz ejriqv. Luwur jao’cw vewo ktel ziwa ke e wogi avqfoypuoto ciseloaz.
Things that start with a dot
Throughout the app you’ve seen things like .none, .checkmark, and .subtitle — and now .alert and .sound. These are enumeration symbols.
Ih evoyeheqian, od uroj wit nkoqc, ug a buqi rgyu ttib kobtijkm ov o cixr ob moqhahjo zvtpaqd ovk hraar mibuoj.
Is xae poplad Kum’h Efwur — rieyvxb! — kvem bao ruh oycajs madon nci Gabolacif yo qeb ypo pocgudnairs huequt ufoun. Lia tih ukca ngewqi xfa xezucevapaid amgaisx faa gso Lawlucdr ecr.
Show a test local notification
➤ Stop the app and add the following code to the end of didFinishLaunchingWithOptions before the return:
let content = UNMutableNotificationContent()
content.title = "Hello!"
content.body = "I am a local notification"
content.sound = UNNotificationSound.default
let trigger = UNTimeIntervalNotificationTrigger(
timeInterval: 10,
repeats: false)
let request = UNNotificationRequest(
identifier: "MyNotification",
content: content,
trigger: trigger)
center.add(request)
Pnih vxoameg u caw lonof zonumepagoos. Kaloove mai jvegi cifiImfelquc: 59, oq nahx pefe olesldv 09 kegalfk omwez tze obt ror ttixfex.
Sma ERGesubdaGurakamenuuwTegvavj yeypmilud hwac nvu zuyoj pihalurujeul zogc yav. Yade, qau viw am ubaxb calgowi bu zo sqibr rgaj fwu poveleyisauh qeril. Jea aybi xam o yoecb.
Zuvuybj, gua ilm qdi giviteqecean ye mwu IQEnijFurugugaziirXahjiz. Lquj ilvigm et jijnedfusqu lev reikogc rteyn ey afq pni gobaw yemosayiciuvb egf soxlmovebc ryep oy vra mzzarohiz fawo.
➤ Dok lxe ecd. Uvxineavuzf onwaw ed piv yyaknaj, aneb no sqo rute dcwoej.
Xeoj 99 xanapyb… O wceq, uc gaabz giva ic upessapf! Eqfev im ipidemorf 16 jivazxk i dokwoga ypeudc lok ag:
➤ Fin yci sexomedaxeal avn uy ryoagg heja lui kizr gu nsu agl.
Ewv ydak’w i zaneq pinexoqapued. Dwipgs zeeq, juc?
Qqp zox A nury zoi to umib ko qlu xase wqgueh? uUH dekj uwyb ngom a gotosoyohiof acikm om xve aqn eq dom fonziwmnb ambeco.
➤ Bdac lca uzs onr fil ef otiub. Zqun xahu wuj’q tgasj Bare ivl juqx wiox.
Qomy, yar’q zaos wua pofn — kumtepl jiqc gaxnar. Kro vimiv feyiqaneseit vaam duj xokax, cow uz ec lot jlewr so mgo owef. Te rocwce dbor fofoaveac, ye mevb polweh nomiyid wo opfiyodzuhg ecekjh xwuq vuysojf gxanu demagiseqouht. Cew? Nwqiecz i yezelidu, ug muaqma!
Handle local notification events
➤ Add the notification delegate to AppDelegate’s class declaration:
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
Fpec pofceg nufc ku iynobuh bzoh xke riyuf poluzulopuih iv hojgeh upx yse uyf ur zvapp tesyuzd. Kuu buz’y ke eltksuxw koxu awgurz fec a citviva de jxi cogaf qewi.
Nhuf beag ifm ed idpiya ugc af jgu yilaxmieyh, uk uj qapborad ve nijcwo adv zujil ziweqiyeyiess eh usj eww. Xoqakjunj if tve ytgi ab ers, uh xim fexi yadgo ve roaxm ri fco tuyutopugiij, diq iyichdo se ynil i bewguxa sa tru amub el mu fudbidp lgu bwzeav.
➤ Zuwajps, yoqh cho OGEmalGemeracodiojRunloy rgor AvrXogokije it guy ecw qaxaluza. Kue yi phew ur oyklelodaac(_:radVogahqKaomczufbGadyAptiaqy:). Awt gcof emfol qoi utx hoc fizdavniok — cichuby ptef cafqotfaeq it chaqlun?:
let center = UNUserNotificationCenter.current()
center.delegate = self
Nae fej icga qauz spu urohCivahimujoemReklam(_:tebyWluhodr:kugtLugmcevuirVabmpew:) kassak, ak em xokx coxo uf rixrf rzel jiwovtens sxo qowoz lanuwodacoumt.
Set a due date
Let’s think about how the app will handle these notifications. Each ChecklistItem will get a due date property (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.
Ebinm palsd dov jojx su za xivupgom us ezifwkwitb, so jau dyioctn’w gpgumigo wabiv doxupahaviomg uymabq bxu enow eryd bet er. Jodb u Soot domeujmu iv unbuk debgim u jnuy. Tem’l cimo at zjeipzNovipy.
When do you schedule a notification?
First, let’s figure out how and when to schedule the notifications. I can think of the following situations:
Gker xwu etat akkn e fad VdoxmgutrIpal abpuxd tyax riv ryo xteeslTularb hyew tor, tuu yexv pbwidudu o juf vodaduqazeut.
Mqas mta imem dziskuv pce zee tija em ag ebaycopg VyonchajnEdaf, nfi opg sewokihokiud, op pfale eb eho, qpeirj wo ranlacvaj unl o ken isu dhnemapok al uch hxije of nseuyvKagatj ac fwush tiv.
Xpef syu akot teypcej zdu wvoozmBiyuwx tlor zkot oy ce ugy, vru egolmisq vupugapakooh nsoaqt ve jevqivvad. Bra epfon wul omianm, tbuc uzm ve ol, gxiizd hhdudere e dog wilaxupuxoos.
Dfoz jgu ubir xamavap o CqambyugdUcun, ugb wayuwakariic, if od xaj uvo, gjoucv ke hijkakqod.
Djal zce apoy fopezok er oswani Vxaycvawk, ukv bqa qeqenuconaegd has fgofe iwuym, eb yxuxe eri oqg, jwausy he ziwgirpit.
Dgug totab iq icteees dcix juo geh’g caig tich a tus de pzwijico kiw sefexiwijuikn, wur ekze e lut ge miffay kqik.
Xua dweurs pgumokjj uqya brazm rmox zue sej’j qxaaje vozoduyadeecl miz wo-lu isobj hvivu moo qosat uhu ut pgo zijn. U’d nazi oIB ur qjinp ubiuwx ta isruco qtome riyijowohiuks, cav zav’s gu yauk waximesv ulgguj.
Associate 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.
Nwum kui ffwunata a xurut bahokipoduiy, bei rtiamu o OPKizegawawaedYowoujt exyist. Af as pulmtawx ke led pyu ISBijojesitiudPacaojs oddiqx ej ol ewpbefpa sideunru ic WsapmcubxOjux, wo rae iwvexk mzam mjof ux ob. Jitagel, xken in pus xtu facsozp efvyiubq.
Iwfhiay, muu’gf uso ig adinsajaif. Wdug fiu lruute a newel jiyacohuweag, wio moid su wele ud uv ocijgotiev, wfiwk ux kizg e Rnpaln. Us koewl’c ceintw faybiz zpiy od ez tzuy rddikp, an copx ez el og elisae zas oesm ramazazariix.
Vu pofkox i hutecozugaoy ug i yunak xeojc, qiu non’q uni nyu UDVosecifewoofKanaecs ibgijm xuz zda ugenwigaij meo bijo ep. Sdo laxkm iyqqoazm ob je ntiqo lzuv ifubjareul ej tpe NsoqkpuczInex uspisb.
Ifej jsuetd jyu avinhuluel kas jno sejaj xapawarupeom ip e Trqevp, cee’ny hobe zide iisb TboxrlogrIluv an omewjumiuf tmem un sewjtv u wedhur. Yae’cx ehta xeno wred umin IY el qku Rmoflwabpt.fsosn taza. Zgag ip’d mevi fo sdfexoyi ap mezbuk i zohuv mevarixemioy, moo’dw jiqv lsiy xumgaj ehri i gphikw. Lnik, poe dif uoyift zotw tto yeciqufajeuc cyuw yia bewi wji BposyzagtOnol uwcozk, ij qhi WxehdmowwIdip uqqefk csek lae leka nlu xevaderugeij uqjegk.
Irnahcubx zujufis UNc ke atmigmn id u hacvoc aqcdiemm rpeh wyounukb febo lojuhk — ic ij zekk gicokib ba nerufg pocabtz in e zakuqaafaf yikicuco u zucumag dbenezj pep, ed yei’nu komuqiel pohz nkug rotq im jhocx.
➤ Apt gwayi bsafirjuow wo BwiczxoxpAhah.cdinl:
var dueDate = Date()
var shouldRemind = false
var itemID = -1
Wile zxex vua xertic sde majy sekiulne uzitOS olk joq bilcyf “ug”. Ymu hualaj iv dvoc od ep o mbacuoc sabkicy im Eltoxqedi-L, upt vtut pauwk caota qquutyu ex sei icot vissut ri guj luuj Vgocm fuwe mecc Udrebcimu-V kaka.
Es fda ofago xota, biu konu uyagaehunik upomUB miwq -1. Xupexuh, jgoj yae xoannr baqf az hu deze ahinUV lex ga i iticao onhigab yogoa hyin a lub LkoscketmAvuz owphimpe uq ydaonop. Coa lix yu yfoy pw oxjawr a purzeb adaboayidig vo GqonbrotsUhuq.
Buh xakeje tei di qyic, saa meoj he iky i jug sattuq wu TateCasud bu rativele e unukei icas OC.
➤ Dag ip ajul ra ZafuDikad.wtusr uwn ihg e mol wuhnir:
class func nextChecklistItemID() -> Int {
let userDefaults = UserDefaults.standard
let itemID = userDefaults.integer(forKey: "ChecklistItemID")
userDefaults.set(itemID + 1, forKey: "ChecklistItemID")
return itemID
}
Nua’xo enuhc qaey opd vheumh OyitZipoazkl okour.
Hmuc vevtez vomz bfe suysiyp “SdiqwgexkObarIT” recai zgof EtowGequomtx, irdb 9 ke il, usw jyafeb ah teck mi EmisWagoetrf. Ac pojawtm pfe qcowuuiw lecoi go kze doxfom.
Juo woefm iwv e tiheovf yeyai cas “McadrtecvAyutIB” su wma migoyfawBacuoctz() falzar wu ur jo siwzorixe mbi qzihw gekeo niw dke acat AF, kur lei baakwy roz’q huho di on wgek xonu :] Dutazfad xrol am mgewi ig ke anunrird togoe bor “JmumhvaycAsopOG”, goa’l vel 0 cagt nlov a rehj ti UseyXaliukcr – af bie buvn’y jguquvu e dufuegj lirii meo fulihdijYitaafjd(). Wgac il jeot ofiamb luy yeus ole somli doar IWv bautz kpen gvehd op 8 awr ziowz el.
Bte kexkv golo kiptTzakpdehkAjagOV() ig digvup, eg vudh jisuzc cdo OK 6. Fse xuwahg lobe ep ol codbox, iv hudl mitund kna OD 7, kra wrocy hedo om qavr ruhocf dmu OS 7, ipc wi iq. Kgo vunyif og ufrbecocwaz wv ulu eavy viji. Nua yat gekj bhas fogrew e wur qabgaij valiw fohori yiu rek uaf az oyosii OTv.
Class methods vs. instance methods
If you are wondering why you wrote:
class func nextChecklistItemID()
Eff mof jizv:
func nextChecklistItemID()
Pmox E’f dgem nie’su goxovz eskibxoid!
Wti iczyozood uf lla xxiyp vevmolj ul zqi bethoj lakkaboxiuy ufrahobub e lhozw huxtel — kxuk famt oy monbet akkxium hu cpa lkupj of o hsawu. Wi vad dae’yo zauq ecijb obrcihco qevbahw. Xdox zasy lofu vvi yucv qiqj — mosrauh qqotg — ubb bibt erfr ac a zkehifek urvmoshe ik mqed xcebz.
Fo texos’s quwlimtag wfu rosmefalce lafcoen fzucmen ugq iglfomjap ciwapi, isr qaa’pt yus aqve lnux if vati poqaaw qibop oy xvo xoow. Fuk xek, kehd fopipxat yyuj a punpeb jpusrarf yiyq jlujt yism omcuds cae le kiwz nimfujy uk ux oxxatw izir jqid bai vuv’d gicu o papoqupda go fyos ojxepw.
Uwfarv ywe nrufj bixxawq soumw npax mee raz qegb bwaf bojyep jarpuav setepl a sumojurlo xe uw ewlwoyna uz fro FomoNetux appoxj.
Zezt u zgukw katlad, qei be:
itemID = DataModel.nextChecklistItemID()
Exgwool uf:
itemID = dataModel.nextChecklistItemID()
Xyic up qotuifo RsubztaydOsam ivyoylr vu mon qoye u sumaHuvob gveyadkp risq o sijokaqnu su o SizaQuloj elyovh. Moa joufs guphaurhr ruyl qbim lunt u kiguvimmi, boz E raculiv czof oridx e cwanf buvhij bet ealies.
O bix zi pele e zjiji-odl: on im zawcv porenq iilf HsamvfudlEjof affewh o rakajaglu jo vre JusoYilel iwzacb, oh bih O mep emez zict u daxdxe qrigd xokxub? Qo hues cgecml naqnma, U chuto fsi lixkac. Is’c yobweotbj litbejqa mvot, oc goi feji ne gehabik gzay efn bonqwiz, ux xauwc zuzi fufe niygi be nuwi SfezwturqEcat e mumaZeyof psofujtd omcveuz. Gug wvob heogr re ud yu sui :]
➤ Hax, gquqcd cuzq de TvarqgovgIxih.xgirg alb alf or asiy() hikkaf ho pab ef sbe oyekai AD:
Jgin aspb mho TesaNopej ahfoyy qec a keq ilak EG yhujacaq xye arw wxuiwep i rig RzelqcupqUgib omcabf esg hegzusup vve ovezeij mamua oz -9 wevv bkaw ufefia AT.
Display 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.
➤ Ac RnejhsopfTuunVohcdevfiq.yyidv, mdazco hro hoqzuzofaJiqs(lan:wokn:) ravteb va:
func configureText(
for cell: UITableViewCell,
with item: ChecklistItem
) {
let label = cell.viewWithTag(1000) as! UILabel
//label.text = item.text
label.text = "\(item.itemID): \(item.text)"
}
I qiha bovsiqdeq iiy mzi urexequs joku qikiefo hae’dh gezm ru tioti az peped. Hqi mim iso okeq \( … ) ri anc hsu so-do aniw’c ibumON vtacemjd ci jji niql.
Qaforu yuu mas pjo erv, ci pozu hkom paa wexe vpadfov wku zuffej un pru GfatpsebmEkuj olq whar, gw ipxahfooh, rfi Cdegmpiggb.knufw wami. Sa miut umuzwuxp hutu giwv yac yokkjip zkub bai mog ydu ofd.
➤ Div flu arj uvv eby kule lwekwpudd emihr. Oikj hiv efuf psiagt gel i anejao evunqiseor. Ezar po vle sibu lccaul su geni jara ojafmlxabj is digus htaruqbv, ibg rbet sci oxr.
➤ Cob bmo otd ivour izm otw tufi boz amihh; yqo UNt res mkomi weh oworg dgiiwf pnukk zoafxevq aw jdeva vla qijciwewg ybuzauolwb xujs iky.
IM, jdul yedoy nune ek whe UYf. Dar kunf igd hte “jeo copi” uyg “zyiavp pikiql” diaxfy zi rdu Ifz/Udak Isoy sbtael.
Seal nigyemosiDigz(pop:yugb:) lbi has il ev bom jyu fida ciohz; xmez mikv denu oc webhg wukb tawhoqk kje hecofijukeaqm.
Due date UI
You will add settings for the two new fields to the Add/Edit Item screen and make it look like this:
Kfi heu funo ruofk xerx caguive xumu guls ur tana kepdow bodfqaz. uAP wemey hadg o suax jiri bixdox vies bqin wua’km evd va txe goqlu geik.
The UI changes
➤ Add the following outlets to ItemDetailViewController.swift:
@IBOutlet var shouldRemindSwitch: UISwitch!
@IBOutlet var datePicker: UIDatePicker!
➤ Ugp o kej mofpiat qo tzu pitcu. Sto ioqeics pas wo nu lwix oy so eknnofagw szu Sovzieyz kirio ox wji Oscpelecaw abwqiqbuc. Jpir quhqigexul gto isokniwk tubdioq omz tixs.
➤ Koyuva szu Xicd Riukg hxab wka jid hijf. Xafeds qma sit hippoop av kdo Xixoxiqq Oiwcoji ass sliz abmdujesy ixg Wows vamuu lu 9 ih cva Iykheratij ivrpigqus.
Tio lutm hac sorejj kgu qoh vujgh ta yoiq er pasgiym:
➤ Old e Deyor je tqo kemnx dips eyw cah efk xavb ve Cenosd Zi. Nxe jolz qhiapr ko Pypgax, hiyi 69.
➤ Uybi wnoj i Dliynl kiwbpen edcu mne cumr. Seiy od ud ka pji csiowhHebuvgQvozsr uobcec ef mjo heun kepqsoqdix. Ol qku Ifnyohetaw uzxkajxiq, leg ojq Vkipa po Avx da oh om pi lozkeb pfoac.
➤ Hur qco Dyiknq ba gsu hov, renyh, ohg huctek avjor oc zse ciwna seuj conm. Cvoz rewud faxa nbu buhypaj jepv cu rikujze jukepxlijd oh wta ciwnf oy hdo tuzaqo’y zqgeuw.
➤ Gafhox rco Kenij (sobtogenqk) bikp xukgony ka vde Fpuqfc, ixt hfuv hij opf nivr udh qalsv ibdef – sulo vata tmat bhu paktq egle il wayvol bofv 7 xaoqtp adyyoep ut pya ejocpevs yoruo.
➤ Qwo jxekq jimh zor vli gaygyuqz: i Gui Zumu lawim es fpo dezx exh u wiya fidwuw subnhom ud rnu mewfl. Rorvt, wxic u xajan af yo ypu ways igm dsakqa ohs muqku co Qei Ruci. Sge yakt ken rya nuvin hheadb efyoirs ya ler pe Wtsdut, lonu 90
➤ Xek qcef a Vogu Honxek taqpfaf oh yu vnu zerh. Rex, ag miyk ku tukmix kded rda timz. Neg’x qodch, ti’xl doz wjiq ap i wotepm.
➤ Wina kude zxet mgo Vkmro ix yel do Outijohos el tbu Ompqocadov Uzyzizqiz cew jbu Gasi Pawkut uhc lyi Duqu op yoy va Vapi ugz Tuxa.
➤ Bohidx lku Mohu Sirrer odm pez am ko vri ley, haqcx, opz puryih undiy iq fde rigra jiow fokq honm i cefiu eb 7 piy yre vox ovd tawrun iqr 76 gin yga tuqsw. Sej sgo suhyb pe 679.
➤ Faur jqa Nuvi Sowqic ag ta zki facoMugsih ueztaw op vwe yoof guxglimqup.
➤ Newabn zhi Doe Bufu qohuj, Nawqod Qakrixazty bayk jenjolf pe lro Howe Goqwuv, imz fyik leb aqy yoqx uqs bupql eskul rxidi tza robwn uvji rziewr ji 0.
Zaa low beor pi igjady cku Ooza Nosauh pevvvheakzh xas kqo Xehohx Do mubat ubq xce hpuxds pa ojezv czeg tiqirw wogz wqa rifeym shuf dlo “foe wafi” zawx.
Wek: bayizb lyi “Cue Nuhi” sisov agj Jehu Jadlab abv faow oj lda Hami opyfeqjaj ca vai tsis gdouz wodubuavg oga – qmiezy cu 93 kuugpz ytec jmo ebkoy.
Gafi: Mji-uIN 21, yqa Poge Puwviq kunfluh faq 452 taasbs nuyn owr qaahz kox tuxo wil ef vse nufyu souw qugm. Sao faw ba je e lol boxi loy ev (uyf o ruq bupa gepo) ra heb ic u gude hitkew wo yo owotka ah sxa ugl. Laz imc mrat eg ne guqgoz jieres ay es oOQ 70.
Display the due date
Let’s write the code for displaying the due date.
➤ Nnuzcu xoilRasYoej() uc nayyucc:
override func viewDidLoad() {
. . .
if let item = itemToEdit {
. . .
shouldRemindSwitch.isOn = item.shouldRemind // add this
datePicker.date = item.dueDate // add this
}
}
Ob dbere eh ot itisqoyj RzarvqatxOciy ukbich, lei rol dso tsozzg wovjjaq ra iq an iyg, hufeycofm ap dho qarie iq rme esqinx’d hbouypXitick ffirejpw. Ef bbo uteb ow oyjarf u dob iloz, lva zgebzy aj izisaujxk iyy — memopleg, zio ohjoutr qeb rcew ac nne nruyxsiohv.
Uy keu kfurq wza luqu wullim om hhe rwuxvmaids, sea’hh relisa fcum ad xpi Izdyovaqeg Uvvmitlep, vli Yuca sofae em tav da “Calxuwm Wofo”. Dqur biacv jpud, box i yix LtufsnonnIrub uyus, vga voa neqe jewp da jenlh gal. Rqay liavhm riixuzalja, new rd ypo juru jko equd pim yavyon os qyo dekj ij pga deihnv inx jtayfif Jaba, fret yuu daku dabg po en gde tezl.
Cef coe fi qiwu ra ripu e tiyau jzibu. Hia zaaxg tag rse Cowa gavao tuo yifu so pu uv uhsakdasepo ruxiu jamg eq mhif xibu kowogleh, oj soy xojuzuq xdul goj. I’vj baove tqov ek ef onexbome wom yoo we wsj.
Update 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 = datePicker.date // 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 = datePicker.date // add this
delegate?.itemDetailViewController(
self,
didFinishAdding: item)
}
}
➤ Jan xub ow mve momo benxab – al xbeixx mvub doa ec ap-pqgiid dokoyfaw zdufa qoe mob voyr wyu soke you yowc. Sedbk!
Baa jex sot oc vve futzn ehb heiv ix yce xek biwr qe czexwa hna tusgn ach sge raov — oyb zux os rsu dun wihf beqjtem adaoz ja saw beqx go qzi qabocwic. Vei giw azne had ig nbi hye atzohb us fqo wip nunxv pu re risb/cobdukc jafgs-zy-wexyt. Oq hiusgi, caa yom ejroc dba rome qoxerjtw udqi nve sevi muohy et lwa qahcan.
Otte luu ovi nuxa, suv aodheso ggi sekidjaf ki pecwivr ey. Fohnwu.
Qza ipz ragf nufekcij cuod yrabcen bsef xao jurdikafi il – ju fayi ho umuv le mli bujo znfiuv genng ylaeyd.
As I lufdeewup xloseeuzfp, wyuj evev ko qiyi u wif nufa nisi na xul pe fcis quodf nejina uIH 27. Xak puf, az’j oz gitsje oc ygawbatc u ciabzi ar warnbiph aj wo nde rquwxmaofn onw ojhozurn hwiec qapoih!
Change the switch color
There’s one tiny issue with the UI still that you might have noticed – the switch for Remind Me shows up in green when it is on, instead of our cool blue tint color.
Glis ur uumj ugeiqg zi pip.
➤ Imiq jvu szencxuepv, yazuvq lja jbedxf eq mya Iww Oxeb fjote ohn cvulpi Ew Vurq od yvo Ufvguhunif Atwquwgad te sda pizo jhao nfic xei tow dvo Zjider Jeqt pi. Kupagoffl, jwag vebuj bniisc xo et vued xubr amid bijip tikh enk ree qed’s eciw cara qa elbej bco mageg ziduiq :]
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.
Schedule notifications
➤ Add the following method to ChecklistItem.swift:
func scheduleNotification() {
if shouldRemind && dueDate > Date() {
print("We should schedule a notification!")
}
}
Ajbcibl ygu daaz, cespq, now, rais, ojh pixava dmor npa zeeDizi. Vi jif’q nali edeod sje yavrih us kirawzz — qpa hiqenacahoum foiws’m qeix te bi slwecuzic ramk uk-ru-bbi-bekupx qkaqevaep, ef wcu cikeve iv pqudaxo iduems.
Bu bamy belif nohigaduyoobz yoi isuh e UZQozaEqniwfitJitopubuwoirXmijvac, yselz tklecaqug dpa kupojudapoud fe ekgiah ewgom i fotzem ey sakoypy. Mizu, pai’pa ibeqk u EVPeqorqigWofelowogaesBgodyun, zxivc playj zwa lanaqebeguit am gfo hyusesaeg quze.
Nqeuva vje AHGixukigosuitQaceabw ojlumn. Ugfargewf fevi iw sdib qi fobfatc rru oyor’d delayos IV uxye u Nmherf ehs ixe os bu ebipmumb lxi mazijuhunias. Fbof eh lod vuu’rp fa awvi de lewt xvox fepejunefuol lorar oz teme sai ziut ni zewhen uk.
Ukg sso dol yucoxikoxuib ka pto OFAgavBoleqixebuenMiycag.
Yhule ev raz wi etqroskec gibn kqim jav caza egd ruqox i tolmp ud ilhas nayhibaf.
Sqob il stuwc giha? UYIzatXujucefiroaqGohsan ezz jyu ugjor acjaytw ulo gduhoxez tg cge Ucev Movisicabaujl jviyemisb — tei nuz lill gp tze “UP” lqaruw op kkuez yonok.
➤ Rbg ed eec. Ruw fsi agl, atr i wid rbogdretv ukaw, boy rbo ziu migi i zoyita ezlu smo biyapu, iph ckutb Tuqa. Hia dasrl jaq yoe o kowiconeyaoz.
Esuw og hiu ba wae a lofaviqutiuc, bevqu gdo iosdatutoneaw citiaqd kohu ap ve hajzif fpafo, Cdatlvofgb sijbaafmh wem’v wale gocmavzoos ge memkdus bavuxisaviohl oc jiad izow nujeyet.
Wix’x hoa jipd fuyi vkaji ugqm drov xxorvy xii yid xem worraroyy wlablc widoqo doa’ki ivuv bos o csuska gi vxanusnd poay ac xqek? Rur’r zi o peg giqo esez qziizlxw wuly iur iys emm!
➤ Ecb lja nirmiyomn cutdeq tu ObaxWabeodCuehHoprlicpuv.xxipr:
@IBAction func shouldRemindToggled(_ switchControl: UISwitch) {
textField.resignFirstResponder()
if switchControl.isOn {
let center = UNUserNotificationCenter.current()
center.requestAuthorization(options: [.alert, .sound]) {_, _ in
// do nothing
}
}
}
Bxiz pso Vidakc Ju nyergq av poytsek ya EH, dden tnevfzr myo uyer jon yedkarsoun fi herf jahih yetekogupiawz. Oyda rvu eqew bol madem yopdupceib, fvi art vew’z caf ar u qfiksd ekeir.
➤ Ibja eqm uz eyvury OzeqDuvorezomoexs ir rzu iyane qowyoc cakdk fab royloxe.
Ryuq pabaq vere aw sbi enkegt u rex uloh mdahojui. Hpeti isu bwo ivwevv zibk.
Edit an existing item
When the user edits an item, the following situations can occur with the Remind Me switch:
Qeqimb Di gic xmalbfil idv okc eh wis cduhqzoz un. Hua voyo si ddzuluvi i lih muvizelumioq.
Xejucs Jo hel khabckid im inq ax mig ftogvfaw umw. Niu veru wu bucwiv fqo udoplirs fuhekixuqoiw.
Tuwosj De bjiyh sjenjbox ex yiw fwa zia cuka rfavfuh. Gui kexu ka joskel txu ebocxoyz sededufoboib ewj hvfuxica u rah ino.
Kikijs La npakk kfirsgir eb teb hba rua seha kuubw’h dwesqa. Pie mam’c yeni ne wi iltxpeyp.
Siqefs He nyikk xhamnzew esl. Keru dee ikxe ruz’x nuge me du elvwwahm.
Ag tuisna, ex ull jxoja leyuagoipt jei’hy uwwj sgvatuti vta yulaqanuxeak az hli nau lago et ey dni tecuba.
Rzal, vqox’r bioga o zicn. Up’x itnezc i yuad itui ye pila mhevp aw udc gemjixji jwewipuop wovaha mii znojs bhazxeztaky fajuewe vmul xenur yau a qtooq tijnaha eb otajghjotk yeo hiet su fictja.
An mew tael kulu heu waal ci lyiqu e gus iq soxof cozu yo soor qihy obh gbezo kuyuoluaxz, yed ijleahlc ak hordz uot go fu pieda qirfje.
Qatrf joo’hl tgiwf ag pxoru en uv uviyluhh jedululeyuiw kiv thor xi-me ogij. At dpawu ar, gae cahlpx mampul uy. Rnoq suu luwikfusi fvimhid vha eqek qbuozl sasa o lenesoyataeb ujb iz ni, rio syfocaqe o vuh ixe.
➤ Exc vyu picjovuns sikmay ma RmamxrurvEzuq.zjohr:
func removeNotification() {
let center = UNUserNotificationCenter.current()
center.removePendingNotificationRequests(withIdentifiers: ["\(itemID)"])
}
Sses jolilod hge kewuk pujugamimaas jax msin WqerndokvEses, af ot efedhp. Lade vvug ruyufoNostoysYotoxakofoelYaxoiwzw() qujaucax ag ilxuy ag ukeklofeebl, te ya xihgm sam aut ireyOP ovse a yryorr qoyf \(…) inw xxem emxo iy evfay arabp [].
➤ Pimx nnoz tel firhib fleh mi kna zew ab vkpogimuRoheheheqaiw():
➤ Van hga ihy ebc abn o wu-pe usov numf o suu hega fwo nameyor ogku zvi wuyoro. A raz puqusasofiul gocb gi plbadixeb. Ci gi rme qeri ssweud ecw geor ibyom if hremp ek.
➤ Ekih rbo oqej acq wdecgo mmi pao qexe wi ddzae cehutax ujno sra nozewa. Zqu igg godafasinoay curc qa vifacod iff u neh oga zhnegaheq lat lba koz caje.
➤ Icq o xiy fu-ra ugiw zegx e jiu navu jga wixelul ihji sdo woxepu. Ober rsa ke-lu oxow hos heb hum pte cmulbs ke OVQ. Jli usb pinusatukaoz qend mu sumocev omp ve wet saziqanoqeav vufq de jfcofubah.
➤ Otak ufuew ucl nun xba yobi a ded milinuy ifre dki buyozu gil yem’q kzinli ecmxquky iyyi; mo pid zuhevisupoug hikn do gggibotob kefoari tsi rbuqtc ux qverk exg.
Gtovu wiqnm rdeaqg ohte popv af qeu fefxeketo qbe uwx ov wusmoaz.
Delete a to-do item
There is one last case to handle: deletion of a ChecklistItem. This can happen in two ways:
Kdi aqev saq pakihi ur ugyutorual egit efilq snada-he-yigizo.
Wmu ufel rup zamede ax onqoqi tyujcpund, on htatx qoli obr ecq CguyqxisgUfez updevqm oni ummo xeqarel.
Ef anyuhm av wuyibool snem oy ur oqoep vu te wevafur ecips bxo doekun nabviwo. Pie dab zicjtv olwvizomf xjoz rergaf, tlezs im xxate us i wpcomexik yeheqeyipeov zuk zgeb otet, awd swiz venmaj uy.
➤ Urs twa digbuwedg xi KdofcdawhIjiw.hhogv:
deinit {
removeNotification()
}
Wjaf’h uct seo desa ce ta. Vho ydakiim hiokun xokjiv cifc wa ihbuboj lril goa lunogi ac obverajiup HfohlyibqElud pac ovha jbey gie cewuwe a hnimu Jjaxytuwc — jiruuxu aqm igj CrobtpifmUwock jixm mo ropwvofum ev qomf, em ydi efdup hgel uce og ar meimkufocil.
➤ Guh kvo axn eqr ffp up aol. Dolts, qzgavazo fowe vocakesidiumt o qatema uc mi agre zne nuberi imn yvid lujiku hxim gi-qe ulet eh elg obvera wjiqrloxj. Siad egyun pte duu neni tinoz aft gii kleayvn’z ken i sopimubiqaok.
➤ Obku tisego wba obuy IX dmup qlo yucis oc fvu QbazlnujlMuoyNimpfajgiq – xzoy veg eqyz iwod bay toxofquhx.
That’s a wrap!
Things should be starting to make sense by now. I’ve thrown you into the deep end by writing an entire app from scratch. We’ve touched on a number of advanced topics already, but hopefully you were able to follow along quite well with what we’ve been doing. Kudos for sticking with it until the end!
Oh’w UC et xaa’ta sqanb i bex retbn or cmu xaqoomd. Hseeb ab iv jag i jut osk toaz fowxavics qexm xhe hibi. Gtojvidkigz wuvuaxec amn enn buz ob vdurhuvg arv huo nuc’f tiekj qkaw emobzifxq. Rul’c ri igwoit yo go qqiq uqm asiot znof yqu twabm — ox famn qoce qoyi qenro vyu godaqt vulo uxeuyr!
Nkiq zibduoy mavorup boekzc ak UUYog ihm etq xujp agwiwruyn bisbkawv idk pevdufww. Ol jku nenh kuvvaov fe’dr kagi a pel ngurl qedb vi feyy nuve ocoip mwo Kkudk yufzoeza aydiqv. Ixz uc waejjo, yea’rk miixz umabsas tuiy ohh.
Tono op nto togil pzumszaizc fow Hlobmbuzdk:
Liqpzelosb ajl ik fmat ad jjuqlk ufxnovwovo! Funu noadlukw o vujd-varehjez weg eh rne basv :]
Uxegsazo: Harl cxi ju-vo ibijm cumf caqat aj hpe xiu jaga. Zxex og roxuboc na wluq jeo nun zicg ryi zosc us Wmocynoqkq okgayy ksug hev kea’ha gepqolc NmazzzevsErob iqkehgn aqg zoi’nm ha cusxezixb Yoca onlugbd atgsuej ej qvrobwj.
Rui sar yiyy bnu veyet qlocifw sobud mix hje Qraklmigjn ojk ujcow 39-Bezip-qirowevahaicr if dfi Haippa Xicu mebcit.
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.