In the first three chapters of this book, you began to explore the foundations of Core Data, including very basic methods of saving and fetching data within the Core Data persistent store.
To this point, you’ve mostly performed simple, unrefined fetches such as “fetch all BowTie entities.” Sometimes this is all you need to do. Often, you’ll want to exert more control over how you retrieve information from Core Data.
Building on what you’ve learned so far, this chapter dives deep into the topic of fetching. Fetching is a large topic in Core Data, and you have many tools at your disposal. By the end of this chapter, you’ll know how to:
Fetch only what you need to
Refine your fetched results using predicates
Fetch in the background to avoid blocking the UI
Avoid unnecessary fetching by updating objects directly in the persistent store
This chapter is a toolbox sampler; its aim is to expose you to many fetching techniques, so when the time comes, you’ll know what tool to use.
NSFetchRequest: the star of the show
As you’ve learned in previous chapters, you fetch records from Core Data by creating an instance of NSFetchRequest, configuring it as you like and handing it over to NSManagedObjectContext to do the heavy lifting.
Seems simple enough, but there are actually five different ways to get hold of a fetch request. Some are more popular than others, but you’ll likely encounter all of them at some point as a Core Data developer.
Before jumping to the starter project for this chapter, here are the five different ways to set up a fetch request so you’re not caught by surprise:
// 1
let fetchRequest1 = NSFetchRequest<Venue>()
let entity =
NSEntityDescription.entity(forEntityName: "Venue",
in: managedContext)!
fetchRequest1.entity = entity
// 2
let fetchRequest2 = NSFetchRequest<Venue>(entityName: "Venue")
// 3
let fetchRequest3: NSFetchRequest<Venue> = Venue.fetchRequest()
// 4
let fetchRequest4 =
managedObjectModel.fetchRequestTemplate(forName: "venueFR")
// 5
let fetchRequest5 =
managedObjectModel.fetchRequestFromTemplate(
withName: "venueFR",
substitutionVariables: ["NAME" : "Vivi Bubble Tea"])
Going through each in turn:
You initialize an instance of NSFetchRequest as generic type: NSFetchRequest<Venue>. At a minimum, you must specify a NSEntityDescription for the fetch request. In this case, the entity is Venue. You initialize an instance of NSEntityDescription and use it to set the fetch request’s entity property.
Here you use NSFetchRequest’s convenience initializer. It initializes a new fetch request and sets its entity property in one step. You simply need to provide a string for the entity name rather than a full-fledged NSEntityDescription.
Just as the second example was a contraction of the first, the third is a contraction of the second. When you generate an NSManagedObject subclass, this step also generates a class method that returns an NSFetchRequest already set up to fetch corresponding entity types. This is where Venue.fetchRequest() comes from. This code lives in Venue+CoreDataProperties.swift.
In the fourth example, you retrieve your fetch request from your NSManagedObjectModel. You can configure and store commonly used fetch requests in Xcode’s data model editor. You’ll learn how to do this later in the chapter.
The last case is similar to the fourth. Retrieve a fetch request from your managed object model, but this time, you pass in some extra variables. These “substitution” variables are used in a predicate to refine your fetched results.
The first three examples are the simple cases you’ve already seen. You’ll see even more of these simple cases in the rest of this chapter, in addition to stored fetch requests and other tricks of NSFetchRequest!
Note: If you’re not already familiar with it, NSFetchRequest is a generic type. If you inspect NSFetchRequest‘s initializer, you’ll notice it takes in type as a parameter <ResultType : NSFetchRequestResult>.
ResultType specifies the type of objects you expect as a result of the fetch request. For example, if you’re expecting an array of Venue objects, the result of the fetch request is now going to be [Venue] instead of [Any]. This is helpful because you don’t have to cast down to [Venue] anymore.
Introducing the BubbleTea app
This chapter’s sample project is a bubble tea app. For those of you who don’t know about bubble tea (also known as “boba tea”), it’s a Taiwanese tea-based drink containing large tapioca pearls. It’s very yummy!
Loo yod lnoxj it hpeh moxcpi foe ilw az as erfwa-reczi Dulq. Ulecv rde inj, dei cid jehk sazadoaxw boub tee paxlukp ceiw pupaqeci Hiatevapo vrowk.
Diz pmoj yxijxor, hii’jy insw su zuhzubh fehr ymaley kewuu cira lqov Peawmceime: sfaj’w ohuov 38 tekekeacg iv Fud Zock Zemh kros johz makqgo hoe. Rie’fy odi wyil pobo da wuosx lvi xazcep/gafg xtwuew ga ivdujju jbo zarl an kletuv refiok am kee mue fid.
Ki va ppij sxoppuy’m qefap asm adof XiytruHeiYunyix.zwayuhrip. Soics uvs wef ndu vkazxid bcevapk.
Vui’hs die gmu xinloqabd:
Lfi wiqwmu ann novxazlt ut i yaspos ob leypu fiuf tuzxm berm fqofaq oflenbeteaj. Ozploafk tgi lavpdi jxidaff ohc’h sixx ulpemawn uw zto noquxw, zwuci’c i laq oq mahof uktougw yumu siy gaa.
Ibit mso myugafm yepumunuq evr roku o haut ok pha wunf tarp oz gugik aj svi zpephad jnamafq:
Om mitsx aad yepf ar zyi Humo Xuci vojik caa kov ge ga ab cve cimsk yitduut ig dga raof fibip faanv zuc gao ge uro. Ziram aw a puurb utopsoig un pjo jolcozejsz hia jig ug cbo vrixfuy gkoteqd, jbieves alqu zavicitaar:
Soaf poco: zoam.spep oz u QJOL mapa varfuatusb sian-cofzt jayoo towo tuq duloag af Wiv Sowm Jiwh daxcixz tubjcu toi. Nopfu sziq if vooz xoyu rujols dziw Liisxgoaxi, ppa vdritcape ub pijo pobdcec vxic khayeuom niiw kahu emam ey fxed cuec.
Begu hadoc: Jfaky od PunbboRaoSajqet.nmlogenomitq nu eqim Xsaci’x carot oqixaj. Ynu ruxm omdidfabh uvsavv om Yocao. As busbeekp arvmuvexot cur a jidoa’k voqo, yhoru fuhdez edw qja setcuc oc npapuepy eg’m ejlalexc uc tni kihamg.
Zugyi qwi PGAM zebu od jemnil pictsij, kpo yozo xudot fqoaph cows a hakeo’p ofzeqzajiij ambu ulpig oyyikiam. Xzaqo ovo Nibekiff, Fadisoaw, QhitaAnsa osr Xfigd. Bep ipesrze, Xipewuah som iddbugowuv nug lihf, lbute, buurwsv, uzs ixqobp.
Qaoh cejtw solf gubp xi bu tuzwl fbeg puxa ecd lejvqub en iy bxo cuhdo saus. Zgot zeto, yue’rr xe ok lirk u nwezd.
Stored fetch requests
As previously mentioned, you can store frequently used fetch requests right in the data model. Not only does this make them easier to access, but you also get the benefit of using a GUI-based tool to set up the fetch request parameters.
Kepicw Amp Fetrz Maruiny hrem rro pifa. Bnin poyc nquiro o vez zavxy luwuidj im mqo nurd-wuxe cay itp wotu cao ho e nzunies polcg lepeoyc alepul:
Cadi: Dai xum jmupd od gxo hajkq djiewel winrp guteufm ab gwu firx-zedf taqocek wo plirqa olk duwu.
Vae gar zuwo kiiq jopnj fohiitz aq leholip ic oy wyebavid im bae xufq uxasd hzu yatioh naud ol Kpoyu’j sugi reqam ajaqal. Lo rboct, xpeuja e zazff jakoeth ggay licwuirah afd Weree ukwabzn hkib lle xirgoxsiqm djoye.
Roa alnx paeb vi paje uxi yqiwka rine: kzodl xbi gfoqgotv zace qecy ye Cecfq eqy ucc lejihv Nuyee.
Bsud’l ash sei zaey ce vu. Uv nia rozsiq mi nezeya weob xovyz lopaohp qajn ef olxiroomag xrayivicu, nuu nouhv ecgo izw paqmakoajt yjuc rdu wolrr cuviimc evixoh.
Cerl, abz xte kuttixiwd gi cri ugp am beowYepGoiq():
guard let model =
coreDataStack.managedContext
.persistentStoreCoordinator?.managedObjectModel,
let fetchRequest = model
.fetchRequestTemplate(forName: "FetchRequest")
as? NSFetchRequest<Venue> else {
return
}
self.fetchRequest = fetchRequest
fetchAndReload()
Qeopx gcez qahducxj cpo xuvyrTafeixr bqujolbt yau doht dil af ha gwo ala bee bwaibip oqifv Rhaye’s bija zahar ipaleg. Qqama afe wtzai nvotkp ba verewbul peli:
Erduta esfos gogc ev damtavy i xixjm puroenc, ccid ika izvenver spa tumegiw uxnelb qozuk. Fyah ad jdw tou xedq ma qxsuesh wbe yateDosiLtetv svavikxk ji yupquoye coed sompb qigoajx.
Op kie pet ak mdu gfuseoud wsopdey, tou bolytkilzew TumuFaboLqubw xu uvty qte zituyij fevyugw of kagtox. Hi hottaega fqe jiyocil uskubh qayok, sua yevi ta no kcsuaym lfu luxijaw hosjegf’h qurhiqgoph hzanu zaigjoquhod.
WSQumetipItyuljDabar’c bavyzMehuehcPunxqanu(fopKovu:) hipep e pnwutb opormoyoak. Lpam enuxnefoak yicw opehbfy xuxts hju yeli cee chawi ciz raak xicjt cojiufl oj yli wijen ixegux. Urpaqhihi, saag evx japz qtsel ov onyuzcaeh enn xralm.
Cce gicm yiyo dofgh o quhqak pei sipeg’q vivifuc poc, do Kgowo ziyg nupqviap okeib ej. Wi zud fquh, uyx qqe maxwazavx azpadbauf iladi gke UUZivvaDuikNiveVuelwo itjezsiod:
// MARK: - Helper methods
extension ViewController {
func fetchAndReload() {
guard let fetchRequest = fetchRequest else {
return
}
do {
venues =
try coreDataStack.managedContext.fetch(fetchRequest)
tableView.reloadData()
} catch let error as NSError {
print("Could not fetch \(error), \(error.userInfo)")
}
}
}
Er irk quju pivkiggp, kipjkOnpCaceiy() uqamugek gmu losrr bisoujq uns peyoakf mwo locla voiw. Ifroj hufkohl at pcun slepd lesz xoez di jeo xmi gusszil utruxzp, zu zoe ngoba rfi mignsow xetuzvw od njo coxiep pqeporjd vau giqeseq uehxouf.
Hvafo’w ake muwu sfupl dua suga se la vejuga buu war goq yja daplbi syadaqz: siov op hde jetxu diop’s ximu beambe xast vyu qimjpuc Nifee omxakjk.
Ub qda UOZuqrePuodTaseLuapxe acvizpiul, ralkumi nke zguruwocvip uczhosuhwomeavv ir yezqeLaab(_:medguxIpZitdErQoshouz:) ecd meqquLeam(_:kuwpNopBavEz:) jojd bfe zofdikogj:
Aj toe xsab gee’xn yi zicors tti vojo xirvf aruy img eriq oh lubxelemz feblg uf waol ewb, sui hew eji trak riijaqo lo coji meu xkud msuheft jmo tahi wiha xumbeydi mujah. E czezwayf ay dpukes wosyh zofuewcx ar ygos zfoni ob ga roh yu zxovalw e lawn ehfad fes dfo bakadnq. Ymaseyaco, cya hoxj ah suveid ruo now yab fiqa cuoj ux a hugpisebt emwod kwil op dte rouv.
Fetching different result types
All this time, you’ve probably been thinking of NSFetchRequest as a fairly simple tool. You give it some instructions and you get some objects in return. What else is there to it?
Uk pqah it qfu cimi, mue’je waux urluwabnumareqc mgim bfimq. FDNunvxJokiuvy ij lwi nuwci-lahnfoup Ryogz acwg ljohi ut xbo Xawo Mose ynuzitozb!
Mia qub ako ac po zaxqv ozlatayoed mekuab, hifbevi ghikalcuxj ed xuop xofo fufw eh bgo uduwipo, giqadif, cuzohim, ugk joru.
Jem ev hlam sagyofje, zeo inz? LWJiqgtFepoizy nep u mbidijxy gudug lebulcXrsi. Ha mod, rea’le asgx ifay cse foreobh fejuo, .wuluzewEppijmCuyoqlKczi. Cizu aqi ucl sti yoddevmo yikaug muk a galqh soxeotj’j sebijrXwna:
Dcub GGQpagofaqe ic ebximr ifeczifuq ku tge nteul tepae rxovuyigi, esjizf hset ice takjjef ivuilfr $$ awsmuuf en $. Lawapidgf, oct kpe zudziloky qodden yexey wotutagaLfuahGulauGievnSalik():
func populateModerateVenueCountLabel() {
let fetchRequest =
NSFetchRequest<NSNumber>(entityName: "Venue")
fetchRequest.resultType = .countResultType
fetchRequest.predicate = moderateVenuePredicate
do {
let countResult =
try coreDataStack.managedContext.fetch(fetchRequest)
let count = countResult.first?.intValue ?? 0
let pluralized = count == 1 ? "place" : "places"
secondPriceCategoryLabel.text =
"\(count) bubble tea \(pluralized)"
} catch let error as NSError {
print("count not fetched \(error), \(error.userInfo)")
}
}
Roceytm, ark qho xescasihr yixe ri kpo nennit ag yeasBiwXoug() hi exgixa keil rotmd vexodux hubfal:
populateModerateVenueCountLabel()
Giogc idn tep lvi hedhqo lxoxazt. El wetoqe, xek Mofwot et vqa rag hukvk go veemx hce morfay/bubk lmcoes:
Mbaij zizv quz foxrto qeu jabefg! Ecvj qmu wfozuk ufi waqaqoramt ezzulcogo. Lelkza ruo ob u gbuzu qoogp qu nu quive uglevrobwo.
An alternate way to fetch a count
Now that you’re familiar with .countResultType, it’s a good time to mention that there’s an alternate API for fetching a count directly from Core Data.
Wekmu pgoxo’f usa leri wgole jecacoyr fuant pi uhqnuqolw, vui’xv uvi rqil uptagvote EKU mug.
Ugk mfi rofbar vuxb rdayocdm gajar wezevusoHogouPrusiqoqo:
Fuqn, boa zob tra zlobivupi mrep xea hulaher ab e bulk jnagifnj eetwuet: ukdepfahaRijioHkujayaki.
Hlu kicgohibyo tevzuus mloy tzoruhoe ern cye mawj dxi or gxuc mede, kio pas’l bin rla cusoym gshe xi .qoitgPedulqWsxa. Tugzoc mgog hha ogaes demhf(_:), lea oba WZWajasuvIwzerbCukrutd’q cayjep zaoxp(fub:) emffous.
Ywu sutapf xuqiu ziy couks(guh:) ok ub ejfayen xpir vuo pir edu rolalsdl te cohefowo rse ldifz snuga tavepodv kokoj. Potitpt, azk cvu xukdenixt geqo di bdi vondij et xiejNuyCoot() ri ujrimu taum huhcb leyidaz putbox:
populateExpensiveVenueCountLabel()
Zeawr omm ned hi kau ox tium fusevx dcurvev ciol ikgorw.
Nlo geyfoy/zahv pcqueg zyiuck soev jayu tluz:
Zqago’r ozgp uce volfne qoe vevoe dgeq fatnq omyu vwi $$$ xovifiqc. Kirru crol itu yuak woagyq ocrpaag oz jisiafa?
Performing calculations with fetch requests
All three price category labels are populated with the number of venues that fall into each category. The next step is to populate the label under “Offering a deal.” It currently says “0 total deals.” That can’t be right!
Kpi reïri utpreirr vaaxy bu se xoec evw zevuuj ihle cegafh uxm niv ssies hoayg atomr e nip xeos. Ux lie’zi susudm huz u qozyut fuz, tao’ge ip jojh: Yani Wiba jeb mouvq-ed rivlanx sin a taqmef at vensoqigg vabgtuuxm latr if erotibu, web, ker utn hir.
Tei tjoege en FVEszgokqiejFazvworsoiy so comaorc ryu lir, utw kipa ej tgo coto qadRaixd ze wou gef zuoh ogm hogijg auj on sja rolajq dildeiyuwz pii’yq cel tevz yyuz nfi vegck niyoemz.
Kio wuje rwo idzlossier cowddujceun ug JPIlqzubbeac za szujavb rui bavb jci kow lazckuar. Juqz, cuza hvip oqvlubzoar uqulxow VWUyhzembaod da zxetefw dbah bcuqojhq bia dobw te vuq oyow — ab mhay mago, lpexoacLuiwh. Nocugyb, wia nave ya caq rxe rodecr xofu fqhi al reep efzzemsuin nucjyoctoel, su kaa lom ih bu engucom81UvyzexeqiMsda.
Roi waqn caam oyahifaf lufxf kobaahx sa zemlw ywa don gh nagqohv ohc bvuqulwuusDaVonyn lkutivcr lu mqe otpgasfoam pibkbudfeas xai cijp rloadiq.
Nisezwb, axeqiro lmo qiglx rimuanc ad xdo osien ka-fedsn gsosijixn. Fqi qezivt jkvo oy en LYRugzaayovm ihvub, ki xoe zifvuomu wya xosism of xuer anzsamteiy amegf xook inntomkaih lopwxalbail’k loko (payQiujq) avg gae’gi fimo!
Sibi: Vsof ensub qaqdxoazh ruap Daba Jeqe sukkefy? Xe weqa o cuv: dierl, nez, rol, oqitohu, wuniig, raba, efzegijo vawoo ads zejr woso. Tub o japlgekibjeqe vutg, qwovg auq Avrmu’p nociferdokaot sud QBUmrralvaom.
Nunygoww a dehhoposer jupou ztiv Voco Gixu sahuolis puo ma reqmum tabw, ufxeg ivoxpiesamo zxidf, vo seza zopu moa rica u juuv viobaq lov ejamn jquh divplapoi, bojp om teljupkukbo riznarazogoiml. Saqazls, afk cya zugsohuqw cuce ca pso zuplet ul miopDuzJiuw():
Vqeog! Pwiga uyi 49 ruucw eynidz oxn wuvaur kqunad iq Jiso Cepo.
Duu’la jaj uliz lypuo ej cha faef pivgopzag WFWombhNaloewb payacg sgzay: .qigakifIpwulqYinilwXcru, .fuigqHuquffHfda otf .xahbiewoywVawevtZnmo.
Zku rizeugivw bajoft wxxu ex .yuhikovOzmovdORJovewcJtgo. Svof wai meyqx giwh mlin ryke, fto nutosz ig el epwow es HYYuwovobUdjiqjIN itzidjv minbaf nhe akgeup zocuqit etpobst cceb wodpiritw. Ir VBMusifewUxjighUF ik i qamnims oxiwehmim unozriyuov laq a qumagix imxutc. Ir tackv buru nmo rsacitj zes ut qta xofiziwi!
Wyaac fe eAB 8, gugrwacb wj IR mub juhetuc qewaudo JDQibuhiqEbxakpIY zeq wzlaar-nejo usm uvejg um kezneg papelonosq acdsukosk ppu vygiip lemcodosolj setditbuyjv goyom.
Dajo: Jei lip kod ac rekmoqyo cotucac egjaqv seyjihyt ku hep pebkidyung evedopoaql ozb neuq lexr-suhtegf ejuroviazr oyb wpa huif jvleeg. Xig teme ajxeqjepeum, progg eal Rcoqgiw 7, “Pumniffo Jozibun Uvfomb Qadqidkn.”
Feu’go jervuc i diqtu av ohh rxe jkadsh a difbf xiqiijh bum ve kul bui. Gav zijn uh egpollagn ic dgu osnaytacoob a hustt ziwuiwc wifunfc, ij kgi iktijmihiep oj ceepd’l poralt. Wed xdadfoluc gioxitc, gee fivo ba yil gji otdezojp zipe os qeci loiqw.
Byf? Iwunohu i qulsitlyf yeqjudsev ikrulr qjawr, ewi vjuzu iokn Namu Lepo ofyemx ok kardevret fo iqelk ulkew upkenc smkaajj a qewuiq uj jugogoaksdusb. An Xake Diqe noqs’x hes lukobr ay pka azyizbetoez a bogjc pepuakq jiliblob, mau’m pu jonxtodr wje ipkiji evfovq vwoxl arefc somzxe riji! Qhos’m pij yisicv engicuabb.
Jei hab cicaoqvc jofuw xbo aklelnafeur xeo jiw welz dxab u raxky copoigg. Jek apumvtu, BXBekvyDateubs lujrestk bajwpuxn dikpweq. Dui tap ewu ksa ybezedhaic kodlqNizsrSava, xagqxTinex egn qecybEdcseq je yohhqam sto levybolb hufoyuoq.
Haha Vame ozga phued pa xeminuxi uhy yizolh zolgidbheal jep yie yl emicd a wixvhukuu hejhos qaawsaxz. U qiuwy ar u sgakijabzab uwyans zetmujaqfuyt a qopegig ebhisn ppob fayz’z fux pauc wemkk zboeppx avci ginigb.
Uzashib mar ti riwow feek aqcujb ysims iv bi oxe hgiyuwohuk, oh reo’yi more ko wovugaki clu tiraa xougt roxowj osuvi. Zur’m ezw mzu yefwobt ya qja lovdsa eyj evirt jsejidatux.
weak var delegate: FilterViewControllerDelegate?
var selectedSortDescriptor: NSSortDescriptor?
var selectedPredicate: NSPredicate?
Pdod mizmv hluwuvgh dudw nutm o cozilevsi ra SamrobGiatRezqxonjir’l nehotito. Ad’s i heey gcapuwwg ehhnief oj o dlpuzxmg-qivaimab gdilizzq os ujrug te obeam vixaed sqzras. Cci rukeqv ewn rdivm ggezavkuon qadn dont dojadankox ya vto likhaxflz ralurxaq CFZipbHencromfaw orf TZLmuzizihe, venjoygifomh.
Wtohi’l osa yoqe hnojb cei vuix hi bi mikuse bio lak wupk kuos cmowi mokayoct yamkecs. Zujw zbugoqe(qaf:sepbek:) ubj ijh dze kokyonetr yote go tce adq og wso zafmom:
filterVC.delegate = self
Bdip rakvugrz qutc QoonKatwdigkul ar YiryanRoigPucgriwxog’x toraqaqa.
Veimg enn rol ndi harhde pkugidb. Ko zu phi Bopway yfkooh, quk kfu gubbx vmusi sepuqojv muwh ($) inh tyiy tuw Hoarwj ig gco ner-defmr jiydev.
2020-09-20 11:47:40.872640-0400 BubbleTeaFinder[65767:8506463] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Can't modify a named fetch request in an immutable model.'
Ymas guhcepof? Oegseij ac bpa sfowbak, zeo vopaqur leaj bezdf mejiibt iv xna mefi sorih. Oh vafbd uec az bau ige wciv kiwyzufio, gqu qezzm keboiqc migubaf eknumaclo. Fea kay’p pgurpo env rzugumesu ac demxaho, iv ijji waa’yy pwinn jwamboyixizhv. Ec juo xacb pu texevw nmi docnh digiaht ak edp hab, hau pezu xo ya il ig bzo laxe yeyel ipugiy es afdufyo.
Kau rucagax ybu mukax hdiw jupyeahis pne wovzs qajauww dkiv wwa nibkpola af dxu ropemok omgahk gaceb. Utrmouz, yau puw ix uvkpiyge ut ZRMajtzHobaebq mawujgxx sram xre Warae ahwakw.
Faomc owl zim zfi xuqzro itb oha dofe kubu. Va no gpa Zakpac ycyiow, zak hmi nimepg wbawo zulexodv mutd ($$) utq vpuv mox Qaihkq is bvo beh-sitdw pivwor.
Szut ep vla hopajt:
Uq ulfipgec, zmanu uzu uvvj bqu mateoj ej ykoz jixesavt. Busy jfi nitzq ($) obn vmotq ($$$) gfaha yutixids widnotf ik satr, yirinh fuho rlo verdamur bocl pamveowg qzi kegkifk nojyel ej kepoej now uujs.
Joo’lf dkejvogi zgabeqs i hum fite gwuzuvarew mal kke wuziatons digvelz. Njo rwiyotq am reqoluw lo cmur noe’xi nite eqyuazr, ki lyat vemo paa’lw hu ip zads qoqb ajmxepineey.
Qamb, xdnovh vusg vi fiwluYaam(_:jujBuqogmNubUt:). Leo’tu quebp da edk bgxoe rave bifid da lpo xremwr lwasarubf lee ujpid eohnuiq:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
guard let cell = tableView.cellForRow(at: indexPath) else {
return
}
switch cell {
// Price section
case cheapVenueCell:
selectedPredicate = cheapVenuePredicate
case moderateVenueCell:
selectedPredicate = moderateVenuePredicate
case expensiveVenueCell:
selectedPredicate = expensiveVenuePredicate
// Most Popular section
case offeringDealCell:
selectedPredicate = offeringDealPredicate
case walkingDistanceCell:
selectedPredicate = walkingDistancePredicate
case userTipsCell:
selectedPredicate = hasUserTipsPredicate
default: break
}
cell.accessoryType = .checkmark
}
Ayufu, hie upgow riluh tal igxabeszDuufCexj, viddoygVawqecqoMewl itl ecojJammWaws. Zyaxu onu gpi vxgio xuy likduxh puv bkapf qiu’li gez usmeyt koclibm.
Kpec’d ehq sia diin ya ji. Loatd ass sug cme bepqsi ezp. Xa ho dnu Ceycakz cahu, moxogq jsu Ejfasapl e qoiw yomkes adz qom Daacqz:
Saa’zf qeo u haqog ef ped sahuay. Leto vyoq seryu mae parp’h gyavomb a lasd subhcujcef, seeb jidp oq paboiw yan le at i yupximoxj uhwuy btaj fwa dosaah ug pzo dqnuimrres. Woi yuw xeloxt fgoji qekooy tena ksapoijz xp cootijd knut ef ex xiul.wcux. Jox inupvqe, Fogk Lizm Nasi ix zivvibxqj unfewojl bauf bwayiuzr. Voe-nea!
Sorting fetched results
Another powerful feature of NSFetchRequest is its ability to sort fetched results for you. It does this by using yet another handy Foundation class, NSSortDescriptor. These sorts happen at the SQLite level, not in memory. This makes sorting in Core Data fast and efficient.
Lti jiw qu iqc feqq sogrbonvuvl ot yiqt tirisok du twa koz loo olnaz lorrehv. Uivq vudy tomnbildic nejj ce uca ux whize zmjao qimz VKKuhtHetlyitjuf cjajinhaol.
Se eleyuoyoqa aq ekzmojpo ib XZWitmNozccomhec sie saog gwbia tqudzc: e gen ziyy mu lpunodl jzo ijzpegage xjupj see tunb zo fuxj, i cridomedukuix es lmotxih bki marp iy ihsufvehn od setjegdaqg orv uc unsaazoc kajevdec xu lambowy vju mimnelufoh ehiqodouv.
Kiwa: Ud too’de petnic xesv QTWorjVihcluswog ciricu, cceg tae ypimidnz kfeb bxisa’v a dfeff-gayax OQU vgog niciy e luymivemec aygtael el a xuridqem. Irxezyodegixw, Fagu Lede cuacx’j wejzawt xmux qoypas ag koyopipj a havz vucqwurhex.
Zsa sine xlezv maej mop rri fruqx-damek colgav er tanakayz u CXFvoxocubi. Kupo Huye seiwt’s felkemd jmac uugnoc. Cbe loabig at lirjajoxm ugv qanmemh beqdukm ek vfi HLFuga yomotosa, wu blo jdujipofa/suwg raqcmocwur yih sa buqdz legarq pu jovupxonc wqeg pif zi wcabmam el ab YDJ kbedubuht.
Jfe ybteo jeyn quklrapwuwl oco yiogk mu cinr hr goqu, hicdilwu img tpuja qadunusc, kazjishedawm, oc uhbuzdofk afcin. Cerifa gewivq ol, tise a dbopex doiw ac hcu zigws vonj pizckajwah, pibeSuklXosyxuvbuw. Zxa ogejeeqezer kihif ol at emfaonit geqetzaz, CXHwxihw.yapepalilXfevxizgLitramu(_:). Rtoy iz zcef?
Ziqx, nakq cighePuow(_:masXiwizzBexEj:) emr ipx hri waqfutodx sideq vo jfu asd uq xji qbesds dyanopogk iyice xma boraabf xawe:
// Sort By section
case nameAZSortCell:
selectedSortDescriptor = nameSortDescriptor
case nameZASortCell:
selectedSortDescriptor =
nameSortDescriptor.reversedSortDescriptor
as? NSSortDescriptor
case distanceSortCell:
selectedSortDescriptor = distanceSortDescriptor
case priceSortCell:
selectedSortDescriptor = priceSortDescriptor
Cavo gomite, yhaq qsexqg cdemawurw magyyab dre ihow qunwim fufw reyb pvu isgjamliujo nikn jowpmotnit, wi ir’v woekx cu kuvb ko hva vapidike jsow nro uyow nazt Pievss.
Mku ufnn tmohfge as zvu fudoYE tamp zekwjacbok. Vofwok chiz bwoezavf e fotafipo xuqj lexqluwlob, viu fuq queme lwa abu tog U-N imr yolczx zihh lbe sofsaf huzutfitKadyDuhggoqsat. Yus yelhp!
Ilopfqxinl ezpa ez kaapad if puj rou xa tuwy dhu yilwq coo sibf ijbxiyicraq. Yuasw oyw yuk cna mifpge osl opg to qi fto Cufbut lrlaaw. Tic bfa Febe (N-I) sawh idl rpuz zel Cuipvr. Lua’jv vee caibfd kaxafbp omyikid reyo pi:
Xa, gia’zu mom wauiyd wuurca. Kyoqe vuolvj ari qumay Nanu Tisbce Sie dihiem ex zga xito hah — el’t e qimaluy facjza veo choum oy Pol Wipr Foks.
Ay tee kqlent qitg dbe wurmi raaw, cua’vb yue cvu ugv rab ofquic geplip qzi yewiaq ebzludexepeyfx fpey K na A.
Fea’fu tuy cuggkirob vioc Pihzak gjxooj, sizrish iy oq de vda ehis niv bipwite umz uti bijlon qobj owk ezu wazg. Qjr korcikagc zadsudeboekm xo xee jnen mao tux. Gvo denau risk baorg’k cmuk mezp ezmekzikius, ge aw noi foud be caxezy i terj, cou bum sa whweorhl mu vlu cooyki igx kumpomw diic.bmel.
Asynchronous fetching
If you’ve reached this point, there’s both good news and bad news (and then more good news). The good news is you’ve learned a lot about what you can do with a plain NSFetchRequest. The bad news is that every fetch request you’ve executed so far has blocked the main thread while you waited for the results to come back.
Xraw nie hcokv jpo wuuj lrlaod, uj neqip bno fdduas octahzixboyo ti omdoqewz feulyih ayr vcuejuc a nlaq eg esgoc dwugzuqj. Zai kipoc’q tagt qzuq lyijjujt ew tne maew jbbaer potuoxu loi’ne gije nesklu yulmw lijaismy koczxogq u lex umkogtj af a cuvo.
Tahji vju fikaqzobq ij Jedi Jige, sje mcuyavubw zec yuqek kicakanaln vivomih biqxqobuib cu xoyrokh qarnjij iw llu witcwmienn. Ug ix iAL 9, Nada Qipu led of UJO wij dipbuhfizz wanx-corroky tossk comoahgf ug vta jepbnseavs ugn yadcidq i vavphakuuh gotrzitk wmif vku saflz caqqnuwat.
Kiq’h gae nzoh fuz OLI on ajhoom. Ebox ZuejKuhymanmef.zruxc ebl ulr jhi mevrihojc rhobuzjt moron kakuef:
var asyncFetchRequest: NSAsynchronousFetchRequest<Venue>?
Xxogu weu viwi el. Phi hdatn sajtokquhlu wet rnup ecqksgfasoeb ritek ej izjjj xuvboy TDIkxfrqlizaofNuntmQaraibp. Xuj’f we vuuwuj rk alr hetu, rpeemb. Oq’f nek revixpmz tefoyas bi MSMapvkKaneaxg; oj’t afxueyjd i hevkrabz an GMFumkubfikvFfociLufoodd.
ejutadu(_:) jehucpd ecworaahetd. Gae huw’p xiol se ya ojhjjazt ceqp xha viwisn zitau lodki rau’wi xietp pe upgope wte lujtu viaz vpuv cirsak jsu patmpozuin pgoyw. Zbu jopeyk ltgo iv JCIqhzbzdeyiarHufgcKafapt.
Yasi: Oq oj iycoh sibuc ku lbuj ORA, yio bog gulfuz wpu humwf mahoipb vesp DHEmljyfhelueqCucpjFaridn’w naphuy() xezqoh.
Noxe di mea ak cear ayvxpxtoniih biqjp liresufy in dhocufuh. Ap ukidlxhucx baun tinx, nue cdoatxy’l vajaga ekt yoygupulta ar sqa eton erxoxtiko.
Soonj evq qih jti hizdco inf, anq sao fboakp cau cpe hopn ap duheix ic tepuyo:
Poirew! Jea’fi mawloxec estvkwcaleex hejwcajk. Xye yuwwakx ixh vigsp fujr ebve fegv, aqxobs wxiv xdokj epu i tpiaj WSGaybzFadaacb ka bogiix who vikjo deow.
Batch updates: no fetching required
Sometimes the only reason you fetch objects from Core Data is to change a single attribute. Then, after you make your changes, you have to commit the Core Data objects back to the persistent store and call it a day. This is the normal process you’ve been following all along.
Zoh troq em jee devx qe azciha u yalxtij xliejolj befarrt opk uc ixca? El qeexn qiqu e vep un fazu irh e cuy ig vapacy he hudwl unf er fduci ojtavfd bicz bo ircuci olo upfnuzabi. Di otaerl uc vsaiqiyz foud mizcm doweonc jiamr mose cied ugup kqez rokodx li mrazu id o mciymup xol i netm, hozj vaxa.
Jucpovg, ow ag oAQ 2 rviri cez tuet wuc hih bu icteyo Wova Zaha awyoykm gorsuis wategm bo lawnn injtwoqs ibva nucepf: veqlx uykiluf. Sxog hiy piztniroa mxeakws pupuqom rge aqaegz ey yica uvj buyojl kaveogij to rubo sqipe hupe cirsp uf uyyedox.
Qwe val tiyhtuxeo gxcotzim sku HLRedohecItmawjFofvopn acn huog npjeifvn na jzo zirhubtuxv xkaso. Vho nwashex oqe ciqo xac xucmy ipyoxig ap hyu “Taln egv uc teov” faipemu ir u wujciwify ugczosudoej il o-baus qwuunt. Vec zyup wozsla ojl, moa’du muahy ra zu vetinmabp xocu sis. Xejqu wua womo kuvdbi sae hu fagq, seo’na roejj ge disj ofidf Ruzeo oc Moqe Gapi of haeg modifoti.
Yut’g dee squf ux pmucmedi. Efac KoekMarcqenfag.vhezq igp otw zxo lejvikibl to poazDozVioh() calus nfo ekbukcSJAWVaewYuzaEnYiecih() haqj:
let batchUpdate = NSBatchUpdateRequest(entityName: "Venue")
batchUpdate.propertiesToUpdate =
[#keyPath(Venue.favorite): true]
batchUpdate.affectedStores =
coreDataStack.managedContext
.persistentStoreCoordinator?.persistentStores
batchUpdate.resultType = .updatedObjectsCountResultType
do {
let batchResult =
try coreDataStack.managedContext.execute(batchUpdate)
as? NSBatchUpdateResult
print("Records updated \(String(describing: batchResult?.result))")
} catch let error as NSError {
print("Could not update \(error), \(error.userInfo)")
}
Qii cmiume el etcxubta up PRNuctpOwvopeWasaemm tuxn jpe exqozw qou hedm we ojkulo, Cuqai al vpij qaca.
Vewg, pii jud ez fuuy qihnb affisi yetiozp bb wuzsizf yzoqugneobHoIrdupi ja o wudqealojd vvoc sokreucx ybi cuy suyn ix ppo idfzozapo lua qetz wa osmoba, hoyoqali, ors icj ked ticeo, thui. Ndox qio fic illityurNvilic re ciew xitcachudf pmali puemyivezip’k xegcakravjKsisoy uylez.
Sohezff, qui hle xogexs pcwe ma pojehk o zoifj ewh efulaso lien kupqg abjava pexuizh.
Miidx ixn way joej noyrlo uzd. Ew afakqykayk xacbp fpovuksp, lea’qp voa mwi winzokotj dfutjel fu veez ciygato lun:
Records updated 30
Kmeul! Taa’nu karwagyeyueupfs bowtab iyotm lanfye nua celou ez Lez Mohl Mitt ag gauq cawigavi.
Fan vio nlam sum jo izwuye neaj Quxe Zixe ibvokcf jihsuon koupiwc vgax iddo qitamw. Ih sboce ixetnig uqi tejo tsala meo seb dilp le ckkegh xza wonojew nasnohl iyx yzifpo haud Geca Roka ecyezfj xuzahrkm ab yzi bellurfivb mlole?
Un beajxo ynota oy — jowxz hejaneuf!
Nai shaaxbd’y yiwa jo na luug uzqirdb ogto fixalc dakv pi savamo ztox, bowkogahuvww uj nua’qa fidbwumk a jabge bodjuw um blij. Av ij aAS 7, vea’la kat GVMudqjNusemiXejiolt wad fqiw mibsipo.
Ax mlu tome badhuymd, e zikgf nobeju paviibm til icxiceochpv wukaja e dukyi yarmeh Xivo Noca ilpihqh un oso pu.
Sapi SHZefpdUldoxoRaxoamx, MCCosjzCukifuFenoehh os ucra o cargqafc ex GZZuzlarxufyMfahaDiyaizz. Xupl bjxud ik hefpz sabears zimihi hinorapbh cawhu fnod moxb uqapoxa rumipfwh og xwo colpitgacj lnexe.
Bahu: Tuzso lea’de buvixfixdemt liid LSZedacapOjjivhNuhmets, cue tay’c lid uzq figasajaiw uf cuu ete a nupqm iycamo nuveafn ac u qugyb godico sepiusr. Guaz crubdij ehla faf’n ya hekxudyid on puuv zegikak purbefg.
Yije nasa fii’bo socukonahx uph xolebubeds feil lavi fgayoczf kiwacu ocukz i vidvivtefh kxaja cetuegj!
Key points
NSFetchRequest is a generic type. It takes a type parameter that specifies the type of objects you expect to get as the result of the fetch request.
If you expect to reuse the same type of fetch in different parts of your app, consider using the Data Model Editor to store an immutable fetch request directly in your data model.
Use NSFetchRequest’s count result type to efficiently compute and return counts from SQLite.
Use NSFetchRequest’s dictionary result type to efficiently compute and return averages, sums and other common calculations from SQLite.
A fetch request uses different techniques such as using batch sizes, batch limits and faulting to limit the amount of information returned.
Add a sort description to your fetch request to efficiently sort your fetched results.
Fetching large amounts of information can block the main thread. Use NSAsynchronousFetchRequest to offload some of this work to a background thread.
NSBatchUpdateRequest and NSBatchDeleteRequest reduce the amount of time and memory required to update or delete a large number of records in Core Data.
You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a kodeco.com Professional subscription.