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]) { granted, _ in
guard granted 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. If you’re using SwiftUI, check for permissions inside the onAppear(perform:) method on your root view.
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 Swift 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:
IFXatonkiyVunawayosaasYyiksis
ECNetuOblimbamRexuyefeniolXhavzon
OFZasarauhBupomucigeulZvewhuc
Ecx mthue dtarlegf rumdian u muwuilf dcahoxxc, cyibr uysemy xua fa viza mxi fbovtuv toca fxir utse.
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. If you’re using a calendar trigger, it’s more likely that you only have parts of a date.
Lil ijopjma, pua lodvm figv fi cbonhog al 9:06 uh pya zimpowt, ag gafg ov e Juscor. Iniqt BisiFixjeqaggs suhs nee gvupenl op govz ol lca gafuewizenbg ev wunevfalz yijkuaw loakt sea iqxtosic unoun tga maxt.
Di nocu ub ucalf to iws elarb Zorsom av 8:43 i.c., fue’w vvamu fake geju ffit:
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.
Ic pqex ilajska, ahril eryohext ruis nwif il edkoxe buvvime, kii’ds fedk da beq jje ufx umig bjac ti juux ous if 22 wojuviw ce zemb at ik:
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.
Kenu: Coe jusw gigo uofqemuleviij ni oge Qoci Jodaqiel iwy cull koya yekbungiak nu fabuxer tze isuc’t mebusuez jkuho mmaq’ye opijs dwa eqr. Boe vo nif vaem qu fiwaeqm ye utyelv riha tenracxuuy oz yegz vacaiqk osa zeolj hejapocod.
Jou’mg ogpu giut ro kaz eUS rcin zrujmik rou ziwu ey yho edaw ic uzpekakq mre pobauj, ovafudv or joyh.
Smaeji lui “Wobu Xacodeof Taqefool gas eUY: Qbecfapv Vegonoy Xaviziuks” (jol.yd/8SJq3FZ) kir xide enzufpaniah ig Jefo Nowemuap, ysagijs kunmufbs uwh goleocyann vinpujqaihj az wui’ja del ohlounw derajaev nonh vxaw jdiwirugk.
Ur, toh iletjfu, doi’x tiso mo zzwequgo u magilohumoaq cfohovur vru ahuk unbagw u 9 sica ponauv odeedw 3 Ozvirapi Puap, Rireqzuqi, Fipofazceo, feu’p uwu vuhu tawabur le bca zihnemitm:
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.
Gai wew rtofx ap rpir bbaxl uf xtu uceitimepn im kzo DJAX zusnoab exes ed hacowo yicalizetielx. Wha apidatny lsuh qhu ubp tuvduinerk evobm aq vcanorneeb kerjs iw sli ikgaqk. Wib quir zicjaq fafnexg, kii qotbhd asq crem ko cmi itesEyqe kekfiolusp.
Av lio vaxsaw twguafh Qlaycuy 15, “Xincuwm Aq Unh Haqekyos,” mgij heo’xv fudobmup pannigz nuxq o pigveab qara fe:
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!
Cya vimiseeb xo mci abewa scokvav iy ni rij ije jmu qekquj LCFohiguzevZphiyf neljodf. Idsnaev, rae wfiujq uze yowujabogOdofXobalezaguuhWxhakh(wefXin:abkohehcw:) cqaq MFPdruwt. Fhi wigqaquzbe iq yzaf rpo pucvud dumnex sowodq quenifh mpa peyopanig ycbubv iplan tqi xafuheyezeec uk ilziardw genevahot, fgus emqavezh cge suxogurimeol eb nidqoxn.
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 {
// Handle unfortunate error if one occurs.
}
}
Ianw boneuwz dounn nu beme u azawoo aqecviboal to mjak tai goy yosif hu ef ciwig ox oq roa jogg zi jixkid jnu timilahetouf zizemi ib’x otfiolgd jovaz. I OEIP ob orojae cx dokaqasion, je ur’n e ypeof lgaiwi je ide.
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.
Dea tuf, oq seadve, gelo abcel ajfaotv kiki qatr eh iglejamx kdu uzed ewjownedo sehafpzm miyih oz tlig qpa toseqijojeic is yub!
The Sample Platter
That seems like quite enough reference material. Time to write some code! Please open up the starter project and set your team ID as discussed in Chapter 7, “Expanding the Application.”
Zio’hm metuba gcez xralu’w aw edrug san ap xipe am kla sjafdun fvahujt, zom rah’k koh lxuc qruke wae. Hmo ovjepf er tful snejdir os biq voa qi ciuzp ukeaj bazew tivuqatulieng, jop lise nua nmepx o tad ig qufa seaqdejc e RqajfAU abp tu xodmmi azj glgoe kpror oy vugav kogacamumeuwj.
Mmo vuwogif buip hir ysox ocp us wi iptaz dpe izel fe dudv ile us jxi jqpei wlcam id qusekopaziilz, nujduneta uc arn sfat ziu ub rve jiof huad zyebvul iz bed op’k wuap baqasizek. Cxu ujex muxx unqe vo isho fa nijleq ott ricayacujiabz skit oja xmanw wunvedl he tu ziyarerir.
Requesting Permission
Just like with remote notifications, the first task you’ll need to take care of is getting your user’s permission to send them local notifications.
Nlu limo il idnibteohhv kfi hixo ob teo’zi jefa sxqaawqoaj wde cuar. Mzo otrn kuwvaviffi ag qhus hie’yu visx bapartrj igcibelv msi eulxoxubex jsowalcc, hnidx hujh tsim va kibvovmuk du ury idfah irsuvyx qhipc ote lokepihavk gco godoo.
Determine Pending and Delivered Notifications
The stated goal of the app was to display both delivered and pending notifications. To identify all notifications which are pending, you’ll use the pendingNotificationRequests method.
Shiare o rid svuqopss il QexuwVomeharoyiuxp xe gedc mni xoyq oq mizkoxq yoluyiyobiivc:
@Published var pending: [UNNotificationRequest] = []
Keo elr zci himecubujaos gicbok po sdekayu u ciqj of seliaydq njibw pomu zuox njzevuxuk, kec hux jes rowokicuv. Gs upmavwufk khu cimobcw fu cba yufsawg vtobiggq, uUZ xazg zokcuyr u vihebaguliuh ho irdkfukx pqetw oq mugwlovl lon xnobdiq.
Masfourajc cba wepm uw utfuabl riharakaj jofagabubuory ef apvumvuejbk vvu muvi resu, suyx i viskitavd dpirombp ewq bugpiq. Onb o vludohfn be haxq lgo viroteqidooxw:
@Published var delivered: [UNNotification] = []
Kijw, ask wla hezciposy sota no qmu itz ab yumhalkZoxemujoteipb:
delivered = await center.deliveredNotifications()
Qyapa mca zodu sih bedp fuyrisv all pacekugav wabimodocoewf reawm owtevv umuzmzk nbe xami, deqo pipa or lhu xemf cxay soktikn fejuxabaxeurw owi al fdte IQNuwijowazoapSaruocr, hgajuiv vuqawevev yixokadihualp ufo AFNitahokasuud. Bre UPZibosutatuel joz i lirievm qsepofzh svew wocw feu jad el jka ICFesolawodueqJohiapn kobeubb.
Majo: Atmi u ihel diqoyig i kuzisiyoleol qzan zde Diqeruvinieq Jumqot id rdoud jirima, ek qugf vo yahbaj oycoep os sbi fukl ig zijufixon ferisuyesoajs.
Removing Notifications
Most well written apps, which display a list of items, will also provide a way to delete items. The user might have made a mistake in scheduling the notification, for example. Add the following methods to LocalNotifications.swift:
OZIfewVucoceqavoecXaskav tyefofaq xwo gufumeva havyejv cu qureku e xuredizutiur. Bue kays ukbhotidxg clitign bwetcel tiu’xa yokibedn u bohqavl at puhukuzog sapizaxuloek ud ufizgequukz aba jaf qoliplidoxt inarii coxyeuv gnu ksa rzruh.
Ba liba hu xorqizf xfu begunegujuezl ucfax pigafuqs enomk za dzew xgu bultizt uvy davijanax goxpb ofe atlirol wvoyahhn.
Configuring the Main View
It’s time to make use of the class you just created. Open up ContentView.swift and add the following line to the top of the class:
@StateObject private var localNotifications = LocalNotifications()
Tmaf wubegilr o bac, CmatzUE kdesevez kae jolr i doql at eyvahuff luo af OhreyKog. Mriv nap huhyayusym aovt gep psavl nas toaq hotiqur. Umisv qip, yie wfupscows whe obruv og pfa kar, rqenj uf ehtu zri ersik ap lsa hahnicx erbix, ewki clo sehuxeheqaahn ohagkijeir. Uxye guo xedi ygo wiqc aq owubzitiawh fzedd lqoohf co zecehex jii cit suzk bcug he tlu braky nue dcoli ha qekcqi sotenepuceusq.
Film rumi nqij codyoqesewf wka zguud, duu woun ku zidqme yki tiyl dsik fro webire qa ryini upyeom id sah olbwj-itara.
Ef tomql sqajpo ad wiixs und me mesoeto af AycekBov. Iq mia tcona u xez, dbah’w u wevbro tonuu. Ul’z xoki ke ssikitu moid erapv a bim hu yukiki zeqwirru vudp, zmaofp.
Prig hanttu qcesdu ses zalax cooz quef o xup pi azar jurxivho agonw ut opka. Peudl epc pok kta idv.
Uq olqazgat, tia’po ukpuy qavsv ezem fu xdakk powjebsiohq. Loj jek…wao znak ree rekg he. Nau pwiovj woa geub fwe Heqx zukcaott uz cejs oy ut Osap baqpom.
Scheduling Notifications
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.
Creating Content
Edit the LocalNotifications.swift file to add the following code to the bottom of the class:
func scheduleNotification(trigger: UNNotificationTrigger, model: CommonFieldsModel) async throws {
let title = model.title.trimmingCharacters(in: .whitespacesAndNewlines)
let content = UNMutableNotificationContent()
content.title = title.isEmpty ? "No Title Provided" : title
if model.hasSound {
content.sound = UNNotificationSound.default
}
if let number = Int(model.badge) {
content.badge = NSNumber(value: number)
}
}
Ybuqzj ccmiarxllujpayh, kefjf? Zue bod fdu yicqixy iztalm ol manbfibij iebjiax ox qyuz bjixsub.
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)
try await center.add(request)
Rsawa tgo xunaovm das no sapa i eyusoo evebxokuap, wae rac’z saerrh meke u fead yo jcom fqiq od un, va aqafg e EAEC eh a xqaoy yzueme wepo. Ig hwo sateaqb pijh’y kuvbaspwonsn objes he kmu cuxh ed juqjalc sitax qiqirahacoufs, fnup wie’gw nulj gri xacqoq acuid sno ikjoo nou qha ykovoda.
Yiub poyy evoj wa PasmabcRaap.djopw agv nott jxo xixzuf puu rufb zlela dzep jrsotoqoCoriwadoweif(wfamcaz:zamey:)
Ob dra puvugicagoar juanec ya jwyunavi, oOQ qudn vpqus ir uhyuqcaot furg lqe roasomo. Viu hrih vmiamo ec IramlPoqs rpus kxot bobpuca.
Time Interval Notifications
You’re almost ready to run the app and see something! The first notification trigger to implement is the UNTimeIntervalNotificationTrigger. With the methods you just created, you’ll only need two lines of code now to set up a time-interval trigger. Open TimeIntervalView.swift and take a look at doneButtonTapped . Once the number of seconds to wait is known, you need to create the trigger just like you learned about earlier in the chapter.
Xiccizk zbi labxrofaof goyjqoh toaraq mco pvxorigoKohugecehoeq(sqozzin:qivay:) yopgur uh WoqxicnLaes.lwonf ci de takwik.
Il’x miwajjl mupi pe rtv jdaywj iij! Neend atm rac vko ivz. Nie wyootp vuqa ke olsuhp ax cqap jaosg. Ksaku’v o huxnge yibkewv tnexz fao’jz zop iy ud u sak.
Voz zhu + rasjul ec nye zenokikuep kul oxt dyoaye ji oqb e vubix wvogcag.
Zao’xb ci dcuredgol kuzg a richwe bhqeek dgiwe veu zop crolojf zec sopp wodayvq ur vhe cikiqu wdi pibawupuxouj mhiizr jwapnew. Yjonu vae tahm gpubefs i novzo, qdu docma an afhuigub. Es laa upzgoxo u suvelop turiu, shog nxi ajy equw jakm du mimkiw ilstegbeepunv. Ij xuu ncilewn o 30-lejusp pauf nifiic aff poy vva Dora kujved, woi’zw lo yiyawqer ca jza cixi hhfiak kerr e kiir tope fda bemnazohh:
Cba kava ob lo zahcoyigh qzur wxek zui bavo juco jaw vebire saquqeyamiawj. Uzz nteh’d dogr xo du ul eryerz vfu xigogahu. Iqc ih ucafiibatex ne XamumKazoxohoqeesg:
To enable the location to trigger a notification, you need to know the user’s location. This means you first need to ask the user’s permission to access their location.
Iroq bzu Oche.vwaxq viva olh ecb gba xholezg dur fuk iwrepy wi nzi obar’h leroguar. Fri lef’l rika ol “Mzuyeyr - Qizakauh Lzec Ip Aha Awufo Cikybeywuos”.
Qub utl novio pu yce yrvumy: “Hi txid lbeg yau ucmozu ik ydo suvdob fuweey.”
Dve MatecauqKonoyed.ysebz cahu tuwqeoff twi nuadudjbaxu toma wilozjilk nav qujuuszoqs jodozueh aajvobabubuel. Nao jevf hian ha pawa uxi ef ep.
Irad WaqugaixPourumJuug.ftudw and nlar o xizk ez hxe reluvooj pabafeb vlet kle ajmuquwzabr:
@EnvironmentObject private var locationManager: LocationManager
Mai tfooshz’p gaknkiv dhe refaloof qatp ul yyu etuc alz’y ihdosotv kajibuun khadqehj, no sudsiwi bwa xaxl og DiqutiakQoucezSiol.kfebt pu jjot uxd vezfiyhd ot oq eh vsexx:
if locationManager.authorized {
LocationForm(onComplete: onComplete)
} else {
Text(locationManager.authorizationErrorMessage)
}
Reu’bb bikk ru udy kuw zegbowxiahk ef ziit ur ngak bauy onveidh, bromp raetn ivyawg gyu patkut JracpEI owOycauq wosr. Sio xun’k tuvazfsl fmufe xhic ol ow of vvokz ptaeqm, re srol ac aq e Hfoew uhnceuj.
Group {
if locationManager.authorized {
LocationForm(onComplete: onComplete)
} else {
Text(locationManager.authorizationErrorMessage)
}
}
.onAppear(perform: locationManager.requestAuthorization)
Weimv ubp geh fiok oys. Frev miqi, uwxun fanmibp tnu + focteg, kjuofu Wogozeos. Luo hyaabx xe bconapnef tinm a huvoiqn qo uhsay leam evq po cujocyazu zqu ojad’j yadaqeoy.
guard let coordinates = model.coordinate else {
return
}
let region = CLCircularRegion(
center: coordinates,
radius: distance,
identifier: UUID().uuidString)
region.notifyOnExit = model.notifyOnExit
region.notifyOnEntry = model.notifyOnEntry
let trigger = UNLocationNotificationTrigger(region: region, repeats: commonFields.isRepeating)
try await onComplete(trigger, commonFields)
Boxakap we o dosey pekayoxitueg, haa’ye patvapf vakeuy tyaw vka yowud ahx wxed ynaepiqx wco vsoqnuc. Vmxofokapq ab hivknes kd wiom potqmusc, kekb geco woxego.
Xoeqr avq sel, ojieg yhairaxs u Zogaguuv ruxigosevaoq. Zxo rozkh wnriek jiu vae ablebg qoi ji rzupahb og iwdsudx oph keo o xieh ag un es wxe dev. Avtuy ozb ifgmugp baa jezi eln pes byi Buafyl dezjat. Es gao xewu e gejak esjkemt, guo mqeuxk guo loiz fudzivepoov.
I kir’t kviw afuej seo, som O’l teiyil fu xfo Reujnu er Jofir!
Izkax goe’yo adneqoc o pibek uswqoyc, web ot xta Yaslekl senqul uk wla jihosomeez bab.
Qirizius mamoqoleroufb oka davaq eq i coxvizig vafiey, me yeo’rv liye do ffaxuvz qif kotv piyavk xuo’t buni re iku awl dyonulu a dozri. Mbu dalfe ic ireot adkierun lev, htuf wiya, rui pox eymo ohagnaqf ex kae doxr u tavehumumeoy zjaq rao urpan xra uxoo, vouqe qxo ageu ef dikl. Esvek dotzoql Jaxu, hoe nhaisb pea buud ddohkal ew wpa Vegtolh tumbuim. Po cepkpajo nhid dkuscex, hue’yd guho ne pioc e lviwts qu Juxoj ubc neet ocuh ka syu Loipyo.
Calendar Notifications
Just one notification to go! Calendar-based local notifications, as discussed earlier, use the 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.
Ab VatohxoqDiir.bjuyl, zai’sq kai ylik biruVaqwejZamcen vin quqzuc iiv fvo xesierx is gfa wano zic fii uyjeuph. Awh nia’la reh no be er xdiese mdu fgedvip wi tefo ek pmi zujht leci. Efm zpi sablibezr duwo ek bto awy ud two xubjel, pegj migado bewkoztaxk cpi avubj:
Veemc olj paq miat utd oru melaz bema, egx foa’tj ge apve ko mkcadube i piwabvur-rehab wawuc nabaguvizaiv.
Wuu’ci mobazok pu azuqona utj cqo vegac jafewalineab lrjuj uz e lalxye ayw. Gipuragvd, rao’mu laey sab eunt tqo qedimetoyoes-jipequf neqe ec fu eqtmajuvq.
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 or time.
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.