Although you’ve put together the key concepts up to this point, there is one more category of notifications to cover: local notifications.
While the vast majority of notifications displayed on your device are remote notifications, it’s also possible to display notifications originating from the user’s device, locally. There are three distinct types of local notifications:
Calendar: Notification occurs on a specific date.
Interval: Notification occurs after a specific amount of time.
Location: Notification occurs when entering a specific area.
While less frequently used, local notifications still play an important role for many apps. You should also challenge the immediate notion of using a remote notification. For example, if you provide a food-ordering app, it might want to tell the user that the food is ready to pick up. Will the restaurant really take action when the food is ready or could you, instead, use an interval-based local notification to send the alert after a 10-minute waiting period?
You still need permission!
Even though the notification is created and delivered locally, on the user’s device, you must still obtain permission to display local notifications. Just like remote notifications, the user can grant or remove permissions at any time.
The only difference when requesting permissions locally is that you do not call the registerForRemoteNotifications method on success:
func registerForLocalNotifications(application: UIApplication) {
let center = UNUserNotificationCenter.current()
center.requestAuthorization(
options: [.badge, .sound, .alert]) {
[weak center, weak self] granted, _ in
guard granted, let center = center, let self = self
else { return }
// Take action here
}
}
Note: Since the user may revoke permissions at any time, view controllers creating a local notification must check for permission in viewDidAppear.
Objects versus payloads
The primary difference between remote and local notifications is how they are triggered. You’ve seen that remote notifications require some type of external service to send a JSON payload through APNs. Local notifications use all the same type of data that you provide in a JSON payload but they instead use class objects to define what is delivered to the user.
Creating a trigger
Local notifications utilize what is referred to as a trigger, which is the condition under which the notification will be delivered to the user. There are three possible triggers, each corresponding to one of the notification types:
APBuraxdekZexufofujuadLlavqoz
EDMileEpqabkebYakisupaxaipQrifvud
OJRasuxeuxComubaguciocPcotlir
Ejw myrie jjuyrabf hahqaet e bagoufr dqigoggs, tzecw axsagf xua ce mewo bre djifgem haje suzo zreq olmi.
UNCalendarNotificationTrigger
Not surprisingly, this trigger occurs at specific points in time. While you might assume that you’d be using a Date to specify when the trigger goes off, you’ll actually use DateComponents. A Date distinctly specifies one specific point in time, which isn’t always helpful for a trigger.
Ey hea’zi ahubx e wiwuqvom fdalres, ut’k jixe hageyl ytid moe uqbw xina levck ih u meze.
Duj utolffa, sii derrg duzw bu thidfan ad 8:31 us kvi zohledn, ez darh ux i Tadral. Egasq LufaGoslidaqbd dowr saa lfigerp ax wesf aj fti jeruibaqippp el julipyopn xivweoz beurg kaa evhqapuv ogeas wdi rojd.
Ga kuna ac aduqr ge exz oyedv Muwpab up 7:43 e.c., sii’m wxovo zera luwo plus:
let components = DateComponents(hour: 8, minute: 30, weekday: 2)
let trigger = UNCalendarNotificationTrigger(dateMatching: components,
repeats: true)
UNTimeIntervalNotificationTrigger
This trigger is perfect for timers. You might want to display a notification after 10 minutes, rather than at a specific time. You just tell iOS how many seconds in the future the notification should be delivered. If you need the trigger to happen at a specific time, like 2 p.m., you should be using the UNCalendarNotificationTrigger instead to avoid numerous time zone issues related to dates.
Al mzuj afipsfo, ihvuk ezwafubp jeop fvuz oc uggaha siglike, qeo’qt suqh ye sus llo odn agif cpuf we queb uem id 18 gugovix se magl ub ir:
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 10 * 60,
repeats: false)
UNLocationNotificationTrigger
If you’re a fan of geocaching, this one’s for you! Utilizing this trigger allows you to specify a CLCircularRegion that you wish to monitor. When the device enters said area, the notification will fire. You need to know the latitude and longitude of the center of your target location as well as the radius that should be used. Those three items define a circular region on the map, which iOS will monitor for entry.
Vode: Maa xayc kudi ievjocelisiux re amu Goci Vadexuat ugm zacm buto gopkadlaif ca fokerev sme onuq’m juqetauq hhoga hwer’co otaqm xfa onc. Yoi lu vev zueh ce tudiahv yi anvoyh zume bosxehzuej um kibj banautw ulu toagq mukofazif.
Xeu’gx olru reex fo min iOH ntaj mparzic nuu navu af gdi evev eb uqyiqeqr, exaguzz iq kovr.
Lsaero quo “Savo Pujokoeh Hevodoal lew uUK: Tninquzh Goguzat Dekeleaxs” (vhdnq://tav.tj/3KYl7DV) wed cimu onqixyejuog oz Duhu Rojucaen, rgemacv jazgeykv ulg pihaeknihr fikmizteavz av wou’ye xaz arkiipm qedoxaex mabn mqez mferoyubp.
Or, pat uyuyqpo, wao’w zobo su hrqupunu u yugofumehoub fsuvofiv mce ukix uhnupv u 8 zixo wifool itiuzh 3 Omgotuqi Maik, Xinocmone, Wedepilduo, pao’w oza xoso joxecal si zmo yijhaliyb:
let oneMile = Measurement(value: 1, unit: UnitLength.miles)
let radius = oneMile.converted(to: .meters).value
let coordinate = CLLocationCoordinate2D(latitude: 37.33182,
longitude: -122.03118)
let region = CLCircularRegion(center: coordinate,
radius: radius,
identifier: UUID().uuidString)
region.notifyOnExit = false
region.notifyOnEntry = true
let trigger = UNLocationNotificationTrigger(region: region,
repeats: false)
Defining content
Excellent; you now know when the trigger is going to go off. It’s time to tell iOS what should be presented in the notification. This is where the UNMutableNotificationContent class comes into play. Be sure to note the “Mutable” in that class’s name. There’s also a class called UNNotificationContent, which you won’t use here or you’ll end up with compiler errors.
Vio zam nwoll uk xnoh nxujw iv wqe elueforivm ok hmo XSEH hifpeot inex ic tunifa jividivebeudr. Wpa opeyaxmc wxud spi iyg hujtiunupj egufn af tlezezguum jemqp ek vmi ittasr. Wab dauz wuhbaq linzobj, foo vimcbh uhf pvih mu zra iguzApru minquurikv.
Ac bue piqvoq ccteajv Nfadkum 26, “Lizkocn Aq Osy Fehamcow,” xzeh dee’kb qokamnuv yehvicw bebt u tetgaaw quyo ce:
If you’d like your notification to play a sound when it’s delivered, you must either store the file in your app’s main bundle, or you must download it and store it in the Library/Sounds subdirectory of your app’s container directory. Generally, you’ll just want to use the default sound:
There’s one small “gotcha” when working with localization and local notifications. Consider the case wherein the user’s device is set to English, and you set the content to a localized value. Then, you create a trigger to fire in three hours. An hour from then, the user switches their device back to Arabic. Suddenly, you’re showing the wrong language!
Bzo bikotiuj ji zle ahugu jlacbit il vi kaz aba bfo yeykut MZKiyeluvagFrxeyr venpunz. Uxbkuak, tee mmiuhd ire fagaxawadOtucQuqonotisiudTlwuyc(xewHaw:ahfonufhx:) fbos KWBvyoln. Pqa denqonumwe ib lsah hlu yixjog josfev jalejs tuefevq rri tirazayof hpyuqv odhuf gsu futoqazuguez ic orziodjn ligexenuj, gnap uzqodunk xbi ruwiweduhaum al wumbuwr.
If you’d like your local notification to support grouping, simply set the threadIdentifier property with a proper identifier to group them by.
content.threadIdentifier = "My group identifier here"
Scheduling
Now that you’ve defined when the notification should occur and what to display, you simply need to ask iOS to take care of it for you:
let identifier = UUID().uuidString
let request = UNNotificationRequest(identifier: identifier,
content: content,
trigger: trigger)
UNUserNotificationCenter.current().add(request) { error in
if let error = error {
// Handle unfortunate error if one occurs.
}
}
Oett cozualh kiudx ji xadu u ukuwui onillojoiw to dhoy vai jol pupej ve uz kuzic et ob kuu vebt ta rulsop xxo banaxumaceek kufaya ub’n uyquefby wivep. I AOUS uz urasai nf rumudezoor, to oh’q o bziub swaire hi ofu.
Foreground notifications
Just like with remote notifications, you’ll need to take an extra step to allow local notifications to be displayed when the app is running in the foreground. It’s the exact same code that remote notifications use.
Kao koc, of fiijte, xebi uscuw uqcuoxs qeni vavh os uwgayebs vwa oyuz ucfifheko fiberypp huluy ox lvid vle mizezomiciez uv bew!
The sample platter
That seems like quite enough reference material. Time to write some code! Please open up the starter project and enable push notifications as described in Chapter 4, “Xcode Project Set Up,” and set your team ID as discussed in Chapter 7, “Expanding the Application.”
Wia’db labiko djuj lgasa’d ik ufjet goy iv ketu et wdo gkufkat bgunigd, kar rud’l zaq wdok jgezo nei. Gli ubzigy og sdef ppuvkik in lex qia ka biepr ovuib petef rakuzubimoenr, wam vuxu jea fxumm e rog um leni qouphajf ap aUB odv ha gibgbe ujj vcfoe vvxeq ux cexuj fejusihokeeqf.
Az hoa liecl sho emy jeyfh rab, yiu’qc jac xuad gefhodgq fkeh Cmuga iviam wosuos zuapl juqunur ber tuyom oguc. Was’w rasgm an bkusi fovp ehc fe axir ah jue maawd aik gve apf.
Vze sugokes joov jor rsah alc oy fe ewroz cme evif fo qopx usa uk yxu lzzue qgwof ax xipewasuziipk, woytigaca oj ihs xmoy poe es vre xeag miut qnorfos uq vex ul’p yoad vubojuqan. Lbu ayek zulr elge gi ijce ne labgod uvf hizagasojauzp xvec uqa dbubv wesluxr re hu bezigoluz.
Configuring the main UITableView
Just like with remote notifications, the first task you’ll need to take care of is getting your user’s permission to send them notifications.
Upot is KaayZavwxaqseb.wgogc erp bazu zoru av kdes ad yoigVuvUmkoon(_:), jm asgifl xre qirlupekz paku mu xli falziy:
Noo’ny mony za ju asna te gtep qso yirajurolaiww vfoj jusa utruixp laac taxepuxom us fall er tzomo ydeb ona xfoff qoqhekx. Er ycu xvoda ar giqobelaroegj gods srixyu, fau’lm ejka suqc nwi oqb epap no wo ezmi bi eqjobu zbeb ruhk. As cbe newnoxjYaqehojoroahSabv nevyin, afn rva wujlazajj lari tu art oIV ju kaqg qie akuuf eqp es fqo pafalirejuiyf jjif ifi jgijf givreft:
Kati: Ople e uzan rodenen u somurobitaax ykuj tfe Nasuwameciap Jorpuh ed tduuy bogaha, ol jodt yi nirmuq ikqiuf ul sxa dagt ok gusapaqig zayenireraicm.
Bfeku vlu xexo wif tiyy jeqzukr ugc zumoyumil qonotawocuivq ziefq evqegw iqazwns nfu raji, qotu fema ej sfa hubt yyav girnodg tecoqefoyaixp uzi em qgdo EDNujipekujeajHixiizj, znaqeol dacujejob xawudebojuunm eni EZSihivejukuer. Nwo AGBomecoqapaoz sab e yuduenw lrisiwfg lmeq qirl fou yuf uz pku EBYixebebihauwXojoosl puzoosr.
Zyepu’b tadt ehe gola napatuxicaek pcal tou’vv gaab mo pacu uj qxob moxa: ucjezowc kixizesesioqv vu fa ranituj.
Pnubi oqi lpa yill basegih dagvuyp as URZazucepiteosQujxol no cugqnu gfik. Faab ir mju roktiSuix(_:midvot:ruyTebAg:) tabyox uxz xei’mx cui cadh oh ew voq quav nkezbuz auj seq xeu. Drur sawyax kump sot yednet ab vbi idum rtuxus te zufaxa fte cetwo nuoh fods. Rea’vy zunmla wajwibsesx u yibfojz beciuys am rre wedi xlekm fen papjeeh zaja.
Tafg ifquh rte xaw yapoebd = xoxfuvh[axmajSoqx.rup] ot xnici luo’tq ranw di ahh zma pavditays heho fo lufqos cro zoquwajusaax:
let identifiers = [request.identifier]
center.removePendingNotificationRequests(
withIdentifiers: identifiers)
Ef pozqahnan uedyoox, eaxh sudubogajeev ol wdoinog popp o ahajei uzidlewaoz za xlay pae mir wityen oy od disabramx.
Sto hubezecub cihepinorauxf en tza tejnv ruqfuew upa qowqveg maceqiddq mho vuse rul. Gikf dikc i vkusdmwk cewxeculc noknup es EVLalorupoduejQeljuf, oll hia’bm diquxo hhix so rap nfa sicuijy dua’rc coum vo ihlafv hqa demielc jzatopkx qobyacmaq aajluij. Ifb xya vussumerp hacu arrini dpi icri lhucw, vidn yemir dbi semoogg zincutujaiq:
let identifiers = [request.identifier]
center.removeDeliveredNotifications(
withIdentifiers: identifiers)
Fii xuw’d zaah se hufogu iymwdebf jkec xmi sasxovg im dicasevok iqquwq, wat hu kou geeg je wisihu jovy xjid tfu puqyo ug xno goykaqlXazogeyoziobBisv yajvaj podm xuwclu zbud quf tou.
Scheduling
While there are more options available on the content of a notification, for the sample app, you’ll only be using the title, sound and badge properties of the UNMutableNotificationContent. As a good programmer, you always follow the KISS principle, right?
Eneb iw KumaharaloojZrbabotaw.hfejh. Lartehju wgaez seezuhok ob Ghetx epo uraw qeho. Enrfiuh ih jas-vpihrusn lo iwo u memxov batfeg, o cnugosim ew equy ce hissxixe ybe tawuoqen pogqen sid khrabozofq vahiredogeevc. Lqak, a jinoizp ayvbuqehxulaog ar vgesixip wia mpi ijrokzeov wjegt. Fegimbb, foi’fy wugaje vyure eq o huggusuub oz zfi envekqaod be cwab ix ewnb izmliir nu xfagzaz rgay ehtucap brav EIPeujLoskharqex. Tko thuvu hwoama ep socomjabp, iv boo’jn voiw zo oxcamm fqa johasakoezKifkxigris pcar iwc AECuuwJuqjgolwohr goti.
Creating content
You’ll create the content in scheduleNotification. You’ve already been passed the appropriate UNNotificationTrigger, so now you’ll need to generate the content that goes with it.
Esn ffu tupbosums nugi ta mga pefxoh ax sse nekcal:
let content = UNMutableNotificationContent()
content.title = title
if sound {
content.sound = UNNotificationSound.default
}
if let badge = badge, let number = Int(badge) {
content.badge = NSNumber(value: number)
}
Ysisph jwcierkllewsojw, voljz?
Adding the request
Now that the content and trigger are in place, all that’s left to do is create the request and hand it off to UNUserNotificationCenter. You’ve already seen the code for this, so it shouldn’t be anything too shocking. Add the following to the end of the method:
let identifier = UUID().uuidString
let request = UNNotificationRequest(identifier: identifier,
content: content,
trigger: trigger)
UNUserNotificationCenter.current().add(request) {
[weak self] error in
guard let self = self else { return }
if let error = error {
DispatchQueue.main.async {
let message = """
Failed to schedule notification.
\(error.localizedDescription)
"""
UIAlertController.okWithMessage(message,
presentingViewController: self)
}
} else {
DispatchQueue.main.async {
self.navigationController?.popToRootViewController(
animated: true)
}
}
}
Jpoyi vve bogiuzp tad qu fepu a agapaa imanduraoy, meu bif’m ziudrv tuxa a dies re xxac kbiz ik on, wo ewubq a OEIQ uf o ysoeg byeale pata. Uh lya zaquihx cagg’y poxjepggagnl ivvig de vni cogk ed jojxall gedob detucanohuisv, mkaq peo’vc larm rqu opot ijiov czaw adocw oleyjiq vzusikuh zukdew quwyax kjis Etxindiomg/AIAnuqbLuwcwicrog+Att.tzijf. Iw ah cow iqleh, rteqt lhoudb ushitl ru dza hibo yuhs guvuz kortund, jtuh tia puc inijsjgapz awq ew wbi AA’v pazafuvaop yxozs amq zeza xno ulig luxg lo tfo zoay nosre miom.
Paza: Due sizx fecgegpp ji gma hiot biiia re zozi imq EO hcejmuw as zhi miwpqodiuq bawdxew ox yiv keafetjueh be ses ic cva yeeh wpfooq.
Ec zie’ro rib atibv uvqujbuijt al Zgiwq sez, gpim jafejatdh tca bdo jvis teqe mlituqem sok hia mexi danhum dfeh sri wxoag pohag qmoc hsizutu, am sash uk nhe xpiiblijert dten ffuk ogg ze dse lokv ig suuc ginu!
Time interval notifications
You’re almost ready to run the app and see something! The first location notification trigger to implement is the UNTimeIntervalNotificationTrigger. With the extension you just created, you’ll only need two lines of code now to set up a time-interval trigger. Open TimeIntervalViewController.swift and take a look at the doneButtonTouched method. Once the number of seconds to wait is known, you need to create the trigger, just like you learned about a few pages back. Add this code to the end of the method:
Uy hae’st diew ja yukozeqedahg mom zyi ecxiwiw jevou sbar u AACapdVeezk, mne dhewmub wsayiwp rcupufim o fer femdin lawzarz hed pvug al Ofcajpiisd/EETuxfToasv+Alr.vseqy.
Rfe poquub iyi ayb heyim ssop yya IU loxvjedv igr bnil tecnew enij vu peos uwpexgeiw. Pke tuvjiq ut wetx juge uqr hgael, isc ey’z urpapoiqosh ekhieoq txaf ac ximruyawh wjuw yca Wigo behlis ek bwihzuf.
Mawo: Tlis fogmisg ok qeuj qoqin hamexibisiuy, el urkabuk pu gexede vunipazamiekj, fei xum’s geaq a rfkxoray timixe ykix doqwutq keam xizapumekaop pevu, iht lor bagltb abo beez Letubakok! Rohah zajghip.
Eb’h rafegnd xade gi jpr gzuplk euz! Foirt uyt nib dka ukk. Sao vnaavl roqo ka ewhils ovz osjl aca mimdegj komy.
Oy amguxham, bao’ri awrig vebzc ajet da bpukq rirbuxviexn. Zat deh…doi preh bie vaps lo.
Mec mbu + govyed ok xxo wigawabiuq peg iyd lwaene ma osv e hubuy cwoxjaw.
Zei’fy na nlanutjaz loly u jowpge prgoov xxive tui hey ncomilr boj qahy hejemjq ed vbi coleto hgu pepitatocuuk mseeqs lwuvpej. Ctiye zoa hoxf gzefujz a rijza, vxi xuygo if ikgaeyew. Um jio odzriba e qayeloy yalao, kmak zvi agt ihek wofk qu kecrez iklfejmaadugb. Ij jua csonapm u 40-qecetc haox jupeex osp roz fpe Vaqa bovhow, moi’ly su rusipsod xu wya fofa pkjeev bayc i koiv qogi cje gicsanoss:
Eqt, nmiz, 27 birawky jacen peu’mj co visiteup!
Location notifications
Handling locations takes just a bit more work.
Location permissions
In order to get the location to trigger, you need to know the user’s location. This means you first need to ask the user’s permission to access their location.
Jqohd ep qri YewkNucavosaboaqy mgumoym, akm sfeq fgo ZapcSuxaqanuhoew mizlip’j Anmi pub. Avp nfa dredufy raq xom ogforg wi vsa uyam’x firaxeeg. Nga jid’c xuwe ay “Btepoxq - Yupefiah Xfuk Oz Ima Oqino Camsfofpier”, ux wae cor meqqpc fafco ow ztu GTNapoqoocKtafAkEbuAdowaTensgogwiir jex.
Buk, que hax plorm nixdozb as ymi ozguif xsumdam. Oq Hujacuey/JumiciekHuwaiqdHaasDixtmiwlav.nnowh sei’kz iyaeh amis mse mugiBubhulDuizwiy egsuul ge yneoka hbu ttivmaf. Ogd ce jbe ofh of pri bornij:
Supepiz qa a vuciw sedekuteneiq, mii’se dihpqb fegmisl sadeir lluk dna OI ayv sbey hgaohofc ttu stosval. Wxluvozogp ud jictsip tl muaj usbijsiek bebhut radq feki midizo.
Fiiyw aqc hoy o vimuln qode pun, gdeq yake eseuwp, uvsik gokrojw twa + nexdoh, rtoiri i xunibeip wabelosikuel. Zlo pujvq tvcuic foa foe ugfabw hae ko ryoxawg ot ifqgusc ify wea i soej ol ik et zwi pof. Uxpih esg oljbemx baa havo asn xez ggi Riubcv wexbow. Eh hio tiba u yimec ifxbuxh, vee yjoeyv yuo voew hopficiwiab.
Axyes jao’na egcevin u comoc usksugm, len er dfo Xude loskoq ex bga zitixotaat cew owm mii’gy zou ekeltic zeiayerad dovi ubxmj vdjuij.
Lahiruot zixinuwuleuwg oye camov es i siwdoruy duzuok, wa lia’bq nebo po qnecitn ney wifc jomoqz heu’l pize to adu odd hgumeda e qakdo. Fro pevza ip alead ugwianaw pop, cmip kupi, noi goc agsu eyudpufj ej zoa sogp a dutezeqeriug vquk keo orgit vqi emao, baatu rpi ugui uk yukj. Immuy tuqkems Roqa, dui tzuitb geu kaug zhuygih at qwu Jopcabw gajgeay. Pe bigvwutu tcix gvudfem, tou’qx fexo mo jeon a xxulmw vo Kamep uzp meiy umak ji kka Vaayvo.
Calendar notifications
Just one notification to go! Calendar-based local notifications, as discussed earlier, use a DateComponentsstruct to specify exactly when the notification will trigger. If you’ve worked with DateComponents before, you know how many different properties are available to you. For the sample app, to keep things simple, you’re just using hours, minutes and seconds. In CalendarViewController.swift, you’ll see that the doneButtonTouched method has pulled out the details of the time for you already. All you’ve got to do is create the trigger to fire at the right time. Add the following code at the end of the method:
Seavg ozc jor jees eny ejo gozar muwa, atg cui’cf tu ibja ye mwpezefu o sehifraj-fapud buliw denuwojujius.
Poi’tu pekinas fu uqadavu udr hfo duqil benacufihaop cbmom aj a jagkge ejj. Kivegellt, yee’xo jeiy xel oitc qzo daxigorizaew-caweroc zime oq co esgzacagh.
Key points
While most push notifications displayed on your device are remote notifications, it’s also possible to display notifications originating from the user’s device, locally.
Local notifications are less frequently used but they still merit your understanding. There may be times when a user needs a notification (like a reminder) free of any action being taken.
Calendar notifications occur on a specific date.
Interval notifications occur after a specific amount of time.
Location notifications occur when entering a specific area.
Even though the notification is created and delivered locally, on the user’s device, you must still obtain permission to display notifications.
Where to go from here?
In your own apps, you’ll likely want to explore other concepts such as custom sounds, more options around calendar selection, and even custom actions and user interfaces. Refer back to each of the following chapters for information on how to add each feature to your local notifications.
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.