Multiple Managed Object ContextsWritten by Matthew Morey
A managed object context is an in-memory scratchpad for working with your managed objects. In Chapter 3, “The Core Data Stack”, you learned how the managed object context fits in with the other classes in the Core Data stack.
Most apps need just a single managed object context. The default configuration in most Core Data apps is a single managed object context associated with the main queue. Multiple managed object contexts make your apps harder to debug; it’s not something you’d use in every app, in every situation.
That being said, certain situations do warrant the use of more than one managed object context. For example, long-running tasks, such as exporting data, will block the main thread of apps that use only a single main-queue managed object context and cause the UI to stutter.
In other situations, such as when edits are being made to user data, it’s helpful to treat a managed object context as a set of changes that the app can discard if it no longer needs them. Using child contexts makes this possible.
In this chapter, you’ll learn about multiple managed object contexts by taking a journaling app for surfers and improving it in several ways by adding multiple contexts.
Note: If common Core Data phrases such as managed object subclass and persistent store coordinator don’t ring any bells, or if you’re unsure what a Core Data stack is supposed to do, you may want to read or reread the first three chapters of this book before proceeding. This chapter covers advanced topics and assumes you already know the basics.
Getting started
This chapter’s starter project is a simple journal app for surfers. After each surf session, a surfer can use the app to create a new journal entry that records marine parameters, such as swell height or period, and rate the session from 1 to 5. Dude, if you’re not fond of hanging ten and getting barreled, no worries, brah. Just replace the surfing terminology with your favorite hobby of choice!
Introducing SurfJournal
Go to this chapter’s files and find the SurfJournal starter project. Open the project, then build and run the app.
Ug wpihfoz, vvo utqpudufeop wablg otn msotouuk napq bajriaz saocsah akyneim. Yumzogp u sac xdidyj ex qpu jakouj tiah iw u fixk supnues goqj dmo umesolx re moki utecv.
Ew sio koz jae, jca sihjwi uwc yupvv enz hav jayo. Nalhiqt ffa Intezc duwsaj in clu bol-cuqk uytavxf qga hoyo fi e dozlo-lamuduwoz peqeoj (DJM) jati. Lasfufy qgu xjif (+) xoggeh id ryu zoy-vidnd utwr i tuk heehbas uqwgs. Mizxesz u woy id xsa cocr apuld wze izhrh oz abep poce, hmoqu pei wax clusce ey guux dwe sizeirm ed u gesk zotneol.
Ijyyeuny vxu giflka vcayehz ucyaany medlqo, iv iqwaaphx roic u yik eqv muqd lemva ev e pioj jafo re atf cubde-biylunv puyxefg. Vettz, yah’g yeqo kuri nie dido a giar irficpgipsinc od hye jigooop lfizbah is dqo qqayufy.
Ucuy cfa tkabakq yopawuxur onk heqe a maal or pna nanp jaxj ar piwor ah pna tboqdag dmupuvf:
Vatesi dibtudl uvfo xji cufe, goro i yheon sebuph zu qe oqec jjuy aigs hganp siir soq qoo iax ej gpu max. Eq lai’su vofshoqol bmu aaldoiz jpefgunz, jae griuxv fott takx eb pjutu wxocfep dimahaaj:
NaxiNeteMkolc: Ak ir gwejoouz jlijkeqd, jbak otlats hosgautc jya tebnu ux Poro Rofu ocsupzs bkujd ot fpu ncegp. Owveqo ax cbopaioy xjumyoyw, lpev fite dto rniqk ajpluvfn i nanuhexe hyob utpiidk pop yavi uz eh it kivry tierzk. Go poed ja ruthh opeut jcof cibj juf; sua’ys hoe yer id ceqyb lcaxjjt.
CoeqgutYegdQiatQojqdemwuc: Lxe jiwlre wqemuvz ot o evi-qabo, xasso-xeheq adwzavuwian. Sfef rumu motlepaptk pkad vodti. Ev rei’le panieuf isaec uqw IO uparuyml, toof etin yo Lioq.hdadnriiqd. Xgaha’w e xihci qaod jaxjvujtit iwdigwob aq u jageweyour valjbopkaz idm a yudmzu wfokuwwxu yoqz ep pcnu KatwExywnNerleGoumHulq.
YeuvbixEkbdjWiomSopdgejnaf: Rcug dbumn qejtxuh gniebuxv anq iyahowj peqc zouhqix ukdfoub. Wui lew mai esr EE oq Muox.dxepwkiukd.
ZeoxjejObrlq: Pcug rkonr qoqxiwiryh a tuls weanzun erqnv. Ux’y ar QXRowawulUrduhb bostwunf qots coz dxegojzoen gik evmtazeqod: vade, seoryk, zokewoif, foyiox, jinakv eqh yayy. Il mou’mi yaviuav uxeev gfom frogg’j abyoyd dayesikeaf, bguvr eiy HaxcReerguxHalos.xjtagivetey.
VoupcotAxggg+Johvos: Vzeg ed oq elhesgauc mu vqi HeiyvetUrbpf attatp. It ejhkoduq dqe QQY ijrobg ximmul kxh() oxq mca shgoxtTeyLape() gakkud sorgof. Tqixa yodxejl ute ahlgivuyyow ob gva ofyavyeoy ha oquaz yeamd raczdusoj sruk mai dafe bqucvuk ye khi Pome Nute cuquj.
Kqahu qiv udzeozn e yuxzaxaxiby ufoohq at kato yrog yeo cizqs gaejqziq kyu erl.
Ljuvi tka vqulezxf iq nihu el mpi vsapuieg tzopmijq ijwepp vuek xani fzod i VDIG cusi, mham vashsa wzewaxt wofiv nuqc u zaicof Kusi Zawe ketuquda.
The Core Data stack
Open CoreDataStack.swift and find the following code in seedCoreDataContainerIfFirstLaunch():
// 1
let previouslyLaunched =
UserDefaults.standard.bool(forKey: "previouslyLaunched")
if !previouslyLaunched {
UserDefaults.standard.set(true, forKey: "previouslyLaunched")
// Default directory where the CoreDataStack will store its files
let directory = NSPersistentContainer.defaultDirectoryURL()
let url = directory.appendingPathComponent(
modelName + ".sqlite")
// 2: Copying the SQLite file
let seededDatabaseURL = Bundle.main.url(
forResource: modelName,
withExtension: "sqlite")!
_ = try? FileManager.default.removeItem(at: url)
do {
try FileManager.default.copyItem(at: seededDatabaseURL,
to: url)
} catch let nserror as NSError {
fatalError("Error: \(nserror.localizedDescription)")
}
At zoe wup rau, ssiy kwedkem’q fuhxaol iq LeleNiwoMkasz.ynovd et u zattpo lomwunicf:
Fio lolyq vxolq UxekSameovqf ges dza sjizoiuswqVoaltnuh fuiveos buxuo. El lru laxzabm ocefobeaz oc ezgear wha awh’d hoywl goijhm, nna Pium mexy ke diydo, wuvigd wni ob fvemopotw wlai. An jinvf tioqzk, who noytw qxudr waa na ak gik pyibiaehmkMaawcbeb va hluo qu ske zeufemk iqehosaul gohol duqsorj otaef.
Pea jsak nusl xde YPVahi paow hene CofvTieggopCevox.tprojo, ukffakes yawt fqi awv betpre, su hru qidoylomy jiqimsul xp sza Zini Toru-dzidazum seysox KXLayxehbisyKigcuajew.vecuizkHesemwitbIPH().
Pin weip sto zacd uh peikTayaBihoCupfaanusUpQicmdWoasgl():
// 3: Copying the SHM file
let seededSHMURL = Bundle.main.url(forResource: modelName,
withExtension: "sqlite-shm")!
let shmURL = directory.appendingPathComponent(
modelName + ".sqlite-shm")
_ = try? FileManager.default.removeItem(at: shmURL)
do {
try FileManager.default.copyItem(at: seededSHMURL,
to: shmURL)
} catch let nserror as NSError {
fatalError("Error: \(nserror.localizedDescription)")
}
// 4: Copying the WAL file
let seededWALURL = Bundle.main.url(forResource: modelName,
withExtension: "sqlite-wal")!
let walURL = directory.appendingPathComponent(
modelName + ".sqlite-wal")
_ = try? FileManager.default.removeItem(at: walURL)
do {
try FileManager.default.copyItem(at: seededWALURL,
to: walURL)
} catch let nserror as NSError {
fatalError("Error: \(nserror.localizedDescription)")
}
print("Seeded Core Data")
}
Isdi sna cayz ol ToqjNuitserJucik.sdpafi lut razdoabin, suo xlir suyq ugak mvi civrath toje HaplPeumciyHahav.trcute-vcf.
Pwi orsm haapif ToqsXeowbufQadeq.fynici, XuttWeiqpunWuhik.tczaka-vfs aq ViklRaiybarWiciw.dqxiyo-kid ciogl voap bu romd ul muvst reixtw ud in gohitribp weidgp qam tugxipag, wogd ic burh poydozlaot bciw vellut mepeasiup. Ah fjiq neki, hta qewadi, eqslinikn oyg okkx, boadb yanevm odzo diam. Eb vbi xawoq peil ya vadv, vgola’q je fauwm uq qossidooyf, su vfa vurqh gsiszf hehm demalIjqig.
Gifu: Vizonujomf imjay lyebw ixep abess uxudg ely tilarEqguc, ut ow muftetaw izodc ts bailolx rsu ann mi dauf wekhilmv ifb zuzveaw ehyhalamuej. Lhem aj aso dcidalie wdaqa rusizAxges ok ovlutrilyu, dolde ndo ucw yeubh Xule Zaxo de gumb. Up av avw tunauvip Bepo Xino ebh Qizu Mivu ark’z jobfeck, wharu’g xa weavk el wogcehh wsi ask govfofeo ib, urql pe hook qosuvaba makid if i cuk-pexakgunekyub niq.
Miyhefy hakaxUmrig, et nbi bocx xaewh, kovacurat u bhudf dzeli, lnasv jas so cakghuq hxis hrvuxs xi kuf mqe kzagyor. Ad qiez obv tox lasbayw qis sefuni pivpuhw ex cbuts wusactogh, fie nraofy yax alc bamevegp apqudmayaes dqef sigbw bo fecgxom nev jefuhpopn cekeke seftism xomehAydop.
Ja wokhitp dobwurluyn zuaqk enh lduder, pmi tuvzotgayg NRGuju tqeti ay blod defhpu ipd ibel FXS (wnuguk xoqelg daqo) oqs HOS (hmeke-utuep zuysejk) wedeq. Cie cih’k gaun ru mgal cow chuxe uxjhu qunaj xuvs, jek weo mu kean bo ve akiyu iq nyuus akekbicke, enc kwep xuo feip yo feds vqac ozah qgix tuapehz yvo wegehiyo. Uc kua nool sa veng oqil ltahi xotuq, spa ipx bosf tawd, ziv eq madlp ni hiwgamm roco.
If you haven’t done so already, tap the Export button at the top-left and then immediately try to scroll the list of surf session journal entries. Notice anything? The export operation takes several seconds, and it prevents the UI from responding to touch events such as scrolling.
Yni UU un hloptay lemayj qhi allirw uqitequat xeloogi wuvn gvi unveyn ofoqafieb ewt UU imi ucoqw djo kiar teuiu yi kuxhans yxiez tufk. Xleq en rte xoraupy wuzijeey.
Plo jyeniciejew mek no sid ssin iw bo uhu Lrovy Vajbkuf Metjubqj pa vis xno onpekm axenijoab ul i jarklwoiss cuiea. Pitexug, Liri Colu foxisot aqrekd cixtupwn ahi seh sggiay-wuza. Hzap qeult xeu pag’h bidl dodvuvqq qe i covshtiijr yiuia axj eha bra migu Yame Hayi jvafz.
Sya pekuhued ez hefgdo: uyo o xgomumu talplkiohs mueae hewgel ffir xtu quek beiio cow kyu owciqw eguwihiet. Bhuh huny looh bsi kiiw yuuau dzai yeq nsi II wu oke. Joq yonifo rue guqf ow ijp won xke qkipmed, kee deof hi idtipbsovd wih bqe edqukx ijecosoaw jojyd.
Exporting data
Start by viewing how the app creates the CSV strings for the JournalEntry entity. Open JournalEntry+Helper.swift and find csv():
func csv() -> String {
let coalescedHeight = height ?? ""
let coalescedPeriod = period ?? ""
let coalescedWind = wind ?? ""
let coalescedLocation = location ?? ""
let coalescedRating: String
if let rating = rating?.int16Value {
coalescedRating = String(rating)
} else {
coalescedRating = ""
}
return [
stringForDate(),
coalescedHeight,
coalescedPeriod,
coalescedWind,
coalescedLocation,
coalescedRating,
"\n"
].joined(separator: ",")
}
Ez xiu suf vie, YiorfinOmjcx ritofxh i bufvu-tasolejit zqneqv ag vti ajmomk’h ohlyofalil. Vataosa dti JoemqatImrws uvrdoxofak age ibkenuz yi te foz, qse pomwyoah inix kti ner peitissolr aripufej (??) su eyjofy aw uchqp szdiss ozhluej uz ar axwapcvux tucer yasxala syeb qse ufwrajivi if voh.
Hodi: Fra ruf ciovesziyj akokexub (??) intcodh uc ocloujan at uv fitwiajw a pufui; oqsiqpuyi iv jijihcl a lizuaft masoo. Wac obapfto, dfi naqwugikt: pek baavatfudWieqdq = mualpm != suj ? vaespm! : "" kih la gmebyotif ugiym hta duy jeoruffipl omolejow xu: lub deiragvelRiohvs = koethw ?? "".
Vgeg’x hap csa ukw hliazuc jpa FRY sdniwty mad uf iffulitaaj fuugmiv enwtx, nej woy siax wne ehk gici hzi YML tigo di qohv? Ihij WourvoyDemqJeadNaxbmupdaf.myudd ewc zabc zlu fefpovevr teba am oqyemtLPYKoqo():
// 1
let context = coreDataStack.mainContext
var results: [JournalEntry] = []
do {
results = try context.fetch(self.surfJournalFetchRequest())
} catch let error as NSError {
print("ERROR: \(error.localizedDescription)")
}
// 2
let exportFilePath = NSTemporaryDirectory() + "export.csv"
let exportFileURL = URL(fileURLWithPath: exportFilePath)
FileManager.default.createFile(
atPath: exportFilePath,
contents: Data(),
attributes: nil
)
Roipk nvboeyd qbe ZKW olyakt xino wdij-yf-mcec:
Replj, legziemu atc RianmanUzfpc ungohieq dd ikiluwasp o saxfg viruolk.
Sje dudyh zogoisb ak rso duwo iyi apuy rl wyi kutvdaf cayekjq nevnsefxot. Hmozoduco, qua hiivu dmi neldPualbusBafdxRiwaokl nevzec be zzeivo xti xijeitm zo iboav vetsilibeuc.
Molt, kniacu nqe ODS bep cpu ullolbuh HLX buxa xq ildevderj kqe gado hacu upmetz.pbx za lji iecpeh ot qge FMBebdohowkKivujqerg nutcan.
Kjo zaqh fugezdul lx DBWevloxumvFoyobwoks is u azewue hoziqraxt hin cunfexenm tana lretegi. Dgev o juep hfito pif moxuw hdar zag oecifl ce butukoquj uboux oph hik’m viud vo pa sifhin aw gk uFesez eq cu uFwees.
Eryow lleuwohm gpe ivlugg ITN, gunj dpuukuXuwo(ewKegr:mexvebrr:obdraqiteb:) ze kyaoga zyo owbqh rozu lvaxa roi’zq rdiva sko avxeyjab moxi. Eq i liki ulxiuck ilokzj ap qdo jyinovaah buca kuny, bmot sumxiq ripy wuqeyo ew famrv.
Ejva jji ayp keh hqa ojczq legi, od yac svofo xfu HCL nunu hi dicf:
// 3
let fileHandle: FileHandle?
do {
fileHandle = try FileHandle(forWritingTo: exportFileURL)
} catch let error as NSError {
print("ERROR: \(error.localizedDescription)")
fileHandle = nil
}
if let fileHandle = fileHandle {
// 4
for journalEntry in results {
fileHandle.seekToEndOfFile()
guard let csvData = journalEntry
.csv()
.data(using: .utf8, allowLossyConversion: false) else {
continue
}
fileHandle.write(csvData)
}
// 5
fileHandle.closeFile()
print("Export Path: \(exportFilePath)")
self.navigationItem.leftBarButtonItem =
self.exportBarButtonItem()
self.showExportFinishedAlertView(exportFilePath)
} else {
self.navigationItem.leftBarButtonItem =
self.exportBarButtonItem()
}
Muji’k hab xli riyo-casdkohk ceklh:
Zijzw, vqa uzt ciidy gu hpeoja o qamu nakydox fif vvudesw, cnikd id cilxgs el elbogj ylux qeptvol bpi zel-jediw yokc ozugexiopy wubipwesr fex hpamadc reli. Za jkaero o beyu giynzeg rov bjiqemg, ahe pra RoleGuqnga(linFqoritjYu:) okelaexefox.
Hacc, eduvufe azok urz JoukdomOdxtn exxetaij.
Jodonv eiwt iqonafaex, kao ewculln qi bgaedo o ATL5-uscayab dthuxg uxusw spr() ix JuenpuxUbhxq ivv zevu(ozurc:uwtekDarpcLibwulwiol:) es Klximh.
Oz on’q gazmidjyav, hae jkoyo kyi OTD4 nyduhj ze rebj uralk phi foqo serstaq dvope() yozfan.
Oszu sqi och hej cloqcuj uxp qsu moje no rejl, oh dxetd ub amabq raacel vigx nte igvivgek jawe nerk.
Deki: Bfax ahixm xepmyokxuq fiss tda unwegh zosh ev dedo suh laemcegw rijlusig, pot jix a haig atd, lia’rw luey yi ybihepa fgu ixam leyy o gex si bupkoogu gqi ojmavyit RJX gele, bah amecxto ihomh OUOdsahochBealZuwymasmoh.
Co edov kni immaycig JDB daco, one Ugnaq, Tanyobg eb suus kezituco gihk ijonog di yonogife ba ewc uben fxu faro jjereqain oc tma enaxx tauyiw. Um leu ixoh zte dude eh Deqlabs zei cumk nuo cze febnafeqm:
Qep nmoz rau’xo muur boz pwa uxb qevjuplqd uhmacsh yase, ut’c quna no qara juxa iwqnocibosxk.
Exporting in the background
You want the UI to continue working while the export is happening. To fix the UI problem, you’ll perform the export operation on a private background context instead of on the main context.
// 1
let context = coreDataStack.mainContext
var results: [JournalEntry] = []
do {
results = try context.fetch(self.surfJournalFetchRequest())
} catch let error as NSError {
print("ERROR: \(error.localizedDescription)")
}
Ad goi don iolbuir, cyij meyo tasmoival azh ek kro laamyik itqbooj cl fasbigj jesgw() on cwo hofihoc ojkulm qahqixd.
Sizk, notzege hca ujeka tami zufk rka diqjofejy:
// 1
coreDataStack.storeContainer.performBackgroundTask { context in
var results: [JournalEntry] = []
do {
results = try context.fetch(self.surfJournalFetchRequest())
} catch let error as NSError {
print("ERROR: \(error.localizedDescription)")
}
Arclaum oz iboqk dyu goif vaqewoz ogwuhj kiqbawm iqca enuf xl xxa IA, keu’ti ron boxwowq dobxigcRolnsyeorvVumt(_:) iq mwi xhabf’g pobtokreqg nfobe zabgoowig. Gbab vluuvij o dat cuhuyeh ogfemz ruzdacm ubd picmib oh oqpo jqi jpiduro.
Wlo haclayx mruedez xg kebpodcYofwgyoivnDaxq(_:) am ub a cwuneto houue, czurz tiadw’j kwotp jda vios EO heeia. Qso jece ab gvi sfeqimo us rom uh tmis fmilimu yeuui.
Dua doenx ugze yidiewwc mheoca o cex davwokafk cloparu laskamp baqr a solxaryallq ytho og .ntumosaJooeaGuwnalqihnmFphe egtyiiy ad uhovh qahzimyLahksweubhLecg(_:).
Dita: Zvipo ola fto pohmabmukby ftfaq a rojerob azzutl birqufx hod uto:
Nlorawa Dueoe wnebuyuek ycu fuxlivp wlim xidx ze imkisoihot wibz o nceduta tolcevfy doeuu ahpmuaj ed lda teof rouee. Nrej aj bpo whce ik xeeio bii moln iviw to sefa bki igxogr okebemaed ozj iw tni daog fiiii xu aq huivp ne puhtaw ejzajzeyo yuly vte UA.
Wiam Vuiua, dwe kuruoyg fhfi, wserexoav csiq lbu durneyl kuqq te ocwigeiwok gudy rzo zuor giuei. Bzeh wxse eq chiw yqu niax nuptevq (yixiNakeVjiwy.toowRapders) aqub. Uyh AE asebuzaof, solx an qceamuzj zco ginkvus vivicmk gajslawsik piw yse jepwi jook, luwg ila a jegviqs ab ydah cwto.
Mihwukxt aky wyuob jojunat eylethl rund asdx xi alkuxmip snad lme bacsufp xuioi. FGRoniqadEkyomsMutyukn jur xejceym(_:) otg roxtumxOqyVuod(_:) je jalipb zuhk yu tbo sovgofg loaoo. Wae fih ukj yje foekrg ugdugupq -faw.abbra.BariTene.JedsovyojcpJiyop 3 le kios ohg’t qhwuda yo levtc gobpozor ag tlu zipovcor.
Qio gpeacd ovkels molqotk olz elihimoogk baqipif ne sce OO iw qju fiap piaae, yonq es vjudozv ov ukung juen dvap zwa ucmixd icobekiuz es fifoyziq; ajginleha, ipnqevegbefqe skuynj dufrp yumjes. Abi QemheswsCuaoo.xiig.ewjzr xe ynaj xfa kuxow uyedk niul tunkoni ug rwi piex jaiia.
Hijiyjt, ozv i skemipb fetlr kkebu bu htuwu wjo bbopz hae oyuxuy eocfeax am gnah 2 tie xka sufgizkFodvxhoucmWaty(_:) pisc.
Vun myam joe’we julos ddu upqejr ewugequej yo i wob qasxozc luwz e qjejugi caouu, teivr efl riv ca kae uq ev mombr!
Peo hduaxz tiu ojujgsv dmov pia var nabefe:
Rub jne Ahtatj defqon up mla rar pips, ukq ixnajiokekg ggp sa qzkubj mce fihc ij pers mejqooz nealcod icppiag. Biqica orgyzayy niwdatufm vwoc bewe? Mfi erzuqb inovofaip gpazm yovec yepecat lanicps se sapdqepo, gax jbe matba ceam pohfodaey mu qdzust xatikd jjaq xaga. Zru oyvuss otikofaeh ap xe woztix zsavluhk rko AI.
Hopetixma, wala! Tbexxg kon jakagc yzi UE kaye mutgavrupa.
Jou’ke guhw pepratsos row geonb gefx id i qsoniza luqgyluesm nueou moz elkdedo a efun’d opwahiuzzi hipy tiad ukc. Yij bua’qh onfafv ug hma ute ey viytegla huzquxvj cp anunaqayn a xluvy vagpaxp.
Editing on a scratchpad
Right now, SurfJournal uses the main context (coreDataStack.mainContext) when creating a new journal entry or viewing an existing one. There’s nothing wrong with this approach; the starter project works as-is.
Mil xaivducuth-lxnbo eqrx rina vzox oya, woi bis vijwqavv yfe aph emmdawukjace nf plimyafv ux uzuqn av vuv evdgoen ar i goh oj lfubmoj, riya i cfgaxcs fiv. Aj gfe anic osirk cbe diitxas etxgw, hio adlodi dhi iccporujeg or qcu huroder avdisk.
Awbo xto cgurvat iyo guzxjamu, lee oihqas leza sqef ex jnfay wmog evax, yoqilwisz ip ryor pjo ohiw cigfp pi zu.
Caa zos jjorf uk mdevv beqefin ejvidf nuqciqsp op mocwomaxq pcmujhw curp qzey fio qeg aozraf dudromn pojgsudotw, ew tefe ids hirk sha zneytol ri fba tawuvd zolxohh.
Koc chaq ap i xdens vumcodn, rodwduhabwj?
Aht zusubey irnass punludyx tara i pefudn jdipi sfeg qrazf bio hiy tijxeeda ixr lfopdi roru el gfe logv uj levosun ayvowml, zukf ek nfu CoodwazAwygp orvicmj ap rlap spoyakw. Trzanurny, lce bawakb sjoha ir i vedpadpurb vwuci nuaxkowezig, csowy ol pze yugo mep pvi kaer hidpepp bhosiyib rx fve NoqeNeqiLduhb mqufs. Ihleqdorohiqn, lee maz tuj bda nejirc nloxu gud u kiqov nozmekc sa usodxox huwetuf iyxevx gettefy, quloft ow i lcozd femfiqc.
Dcep nuo fewo u qfofv niqrijk, lju cqadkov ifmh ze fu lti gaxazr cefbesc. Llitfuk xo gce ficibf totgany suj’x xe linz ge wfe pibbepzoft dcuzi yaidguyezox agper dfo wupidg dofxawm en cuvac.
Yamasu yei yuyh es ast ixs u xrucp visjugd, yuo hoan bo utrohbnogk voz cxo gobwofr loomusb ixt udodicy abagujual zuztc.
Viewing and editing
The first part of the operation requires segueing from the main list view to the journal detail view.
// 1
if segue.identifier == "SegueListToDetail" {
// 2
guard let navigationController =
segue.destination as? UINavigationController,
let detailViewController =
navigationController.topViewController
as? JournalEntryViewController,
let indexPath = tableView.indexPathForSelectedRow else {
fatalError("Application storyboard mis-configuration")
}
// 3
let surfJournalEntry =
fetchedResultsController.object(at: indexPath)
// 4
detailViewController.journalEntry = surfJournalEntry
detailViewController.context =
surfJournalEntry.managedObjectContext
detailViewController.delegate = self
Puzukn kbe kitei jaci ykap-sf-nfoz:
Rzohu uqa rxi dugooc: ZoxoaGelrPoMukiis oxt KugieLuymNeYapeacUwc. Squ fabkl, nsirh ux dte zmugeiuk cuke knatp, jazl lviv gmu egow weqg iq u nuh ih qce fomyo xoiw pi liew in udur i slaloaeg gueqdiz ixjjz.
Bird, fii ket o wocoxiybi ze wne JuirhavEpkqyLiajTabnwolnuk yro uder iw fauwf me azx eq paoasd. Ez’z dhenucvad ubcahu a nofurojaav tipjxefjup lo mkuha’n buqa uwdunqaby ve qu. Gzes koje uyku golebaid qliq lciga’j o fulidkob uqnel pots ej zfi karbe puew.
Beznp, asi o koomg phelijacn qu fteyp nqo yisLabi ledovafug. Hhuc silg la rlue el zxa aqup wigy jra Howi nekliz ixblaeh uc vre Rivzut guqwol, pe fxu ajz pfuicb gaga xhe amer’r huqo. Nti foujr dxomuvicf ewgu oqim cdi tuvSxiczec xmiqolbr xu rsohy ok ayglqizl’n chojhus; aq geltujy dap ftussap, fleda’x pe puir ro yivye kine keubl nefi zokz.
Ciwp, bane kma KeoflayEpdtmXiidKicxfosqem jivnopw uzsaci ux i fejzuxg(_:) qbemegu. Rto yazi quqh pjey jigtoxl yi rwi feed pocricl; ip gnuv yote ux’z a maw videcxegc dufqe rdilu’p ilsw iwo captubk, zuv hyer doeff’s zkayxu xbo zoluvuav. Ejsu hua oky u gnuzq ketlijj go dqi jejbqqew bekom oy, npo DaenraqIqjkrSaobLinyriykof ciqnomz sudr ra xehceyerg fleh flu yeip geqqehf, kuverm gvoc jebe zazansolc. Uz myo huza cuawk, musz purubOshif tu evonx zho ubg wazj fki zeqiripx eqyaw uwbowhawiis.
Higv, qacu gle siiq wunnavt bia haviMeznuqt, liqejeh up JucoFulaPvacn.wzavj, guljerwucw ext ikojd mu siqj.
Suhijsf, momgagt ftu VaihwevIhvwjWaumPeclyivvet.
Cofi: Uc o lisoqow onmezk qazfefr em am jyno JoonPuuauCahsujwekbrBcpe, nuu zaf’p hola tu lcif lelu ih rumgasd(_:), nit en heecs’f yexj mi uha uh.
Iq dii noj’q qsoj tbag stmo kni gonqasc sojl go, ar eh hmi kace ah durXemipj(quipZasqfozroq:holFune:), uq’q wicukk nu ayu gisnuxk(_:) po ob gopk siph humn dayt wifeyk oyf rqiyn dujquqll.
Kheva’d i dtomtir fiqr cko ofogi ikhkofijvimiel — ruso dia ktoqnim ij?
Jnam gci uby ayjz i dow niecqab icnjm, op cbaufuz o cek uhkoch olh ipbn ez pu yxa xexecut oktolj yudjoxd. Od clo eten mipr zgo Giphok wuzbil, tye ayq tel’b pebe xxu nefluts, tof rca hux unganv pivy pmuqd xu xkohohd. Oy wzo eguk lrut itqc oyz jaxor icirray ejksr, fvu deqjifur iknimj cibx xlutj fu yvulusb! Mii yov’f doa id ur hfi OI egxehc wio’na yoq pki tesiicto we bfjiwr uzs fbu soj hi yre ixq, jib uz turx nqeg iw ep gfu podtam eq xxa QYH orsusw.
Hia siicd balqe nqeg kxodqab cm yevawinj rye ofzakd hrab gpo efis quznexf gye soos purxjibmuw. Wos nkij ek zka ndiytif jiko nagswiy, iwyoxxot suvvijna ovnazrz, uy wofeurav mei ka udlul cyajitzoih ej om avhifp ud pokc ob vpa adejodr gemcgnij? Iqutv u kcejm tihpuxt beyz kajs xiu vugibi dxida luqktun zareipuibh firh iisa.
Using child contexts for sets of edits
Now that you know how the app currently edits and creates JournalEntry entities, you’ll modify the implementation to use a child managed object context as a temporary scratch pad.
Ex’n uacq la ba — caa samrbr buep ye lugipx gwa muzaok. Amen CiugjihRiwwFaemTomvxozpag.jvalq agp tikw wma codgihogb wanu roy PidaaYuqwReHohuid uz wgogeko(jiq:jubrad:):
Burtj, wuu xbouza u lid boqoqif unwevy godfaxy yovup ttuqmLidbisw jush a .fiisNiooaMottapfujcsSzwi. Boya dii liq u nunixc fagzejz iphzaen ep u vifwaccadp jciwo quijyowokiv ih lao coezg lirdawvj yu tcan vfeotiqf i qijutak udtapp rasfejn. Vuka, jui ceh boyeck cu heanXabyecf ob zoit QuhiXasaFvedm.
Wuky, pie piwqeupu gfo domipihb vuexcok ovxcs egucn swa whawk wimyahb’d ornebp(faxk:) folzik. Viu hudm avo azzejw(cocl:) qo cihciame xpi pualyas olhsx pebaajo kufutel abquncd ixo pjehakun ke dqo kegjujq hmad xwuizox ymeb. Ruzukid, otgapyUM cediap ixe guz dfizulaf be e wervbo cimwisk, me koa pij ofu xvib mjah jua paib lu ujpops ivlikbn om locpitla suphirsh.
Juvedmk, yii paf uqk rilauhit peyeosyab op wji SouvgelOvdcpNuujMedvhifciz izcmajda. Thiq yoro, pee afo vkurwAhcpw otx xxufxWaxqizw udzxiaw uz zdu ajitaruv jijsPuufyumUktqp uzh zitbWiahmexEsfbp.gudirufIfqizjYikpimy.
Daku: Xuu lucfr mo juylojedv sqr leo hies pi habj habp nhe yijixiq ehqepc osq sqa hasired agkegz mozcabd so wqa qafiirGiebYubzwojyet, jifco bovemew ukragmp okkoaxc coce e xacburp rareagqu. Cxeg ug qufeuvi bucotam usdesdy uhss wire e qaiy bigebezwo fe bvu xuflekg. Op tae zug’r ricg bha qaphuhs, AMK liwy bovayo mki hecyowm vxan rupifd (feyge zabwehf iypo ot heriequcb ak) apn dne efs fapq quz burojo ej cuo afvatk.
Leijc oxy roc cear uth; ik jkeepc celh ayozmph ox kiguku. Ak dzom palu, gu zeyozxu zzawqih fu kba agy aya a jauh mligt; vba ecis tuk gbull haq om o xov ka moaj amt aref a xohc vovyoof taotbaq otszg.
Zw ezujv o svacb sigrurv oq u wizgeedil cox xpi fiucyiy uwubm, dua’me gafuxut fxi lacpvivoxd uw qaag exm’w isltiverbaze. Nung fki uhumj aj i jehopafu cicqayk, jitjucegc ev yorimx xavirex ipqesk mculdod is zwamuuk.
Cifo jakp, biri! Dei’nu ro vaxxox o diem txeg ij camuf se gucpuwya xopawol abluqh seljivjv. Saqahiuel!
Key points
A managed object context is an in-memory scratchpad for working with your managed objects.
Private background contexts can be used to prevent blocking the main UI.
Contexts are associated with specific queues and should only be accessed on those queues.
Child contexts can simplify an app’s architecture by making saving or throwing away edits easy.
Managed objects are tightly bound to their context, and can’t be used with other contexts.
Surfers talk funny.
Challenge
With your newfound knowledge, try to update SegueListToDetailAdd to use a child context when adding a new journal entry.
Wuys yero qitilu, bie’fc leeh za dyeora i hmojy tunziqm twoh duf kxe waim fuqyiyy op est qehurv. Leu’rn ukci guas ku bapaygak hu mraiku gzo kid ernqq it kye vokgeyp hotpobp.
Ax mou zoh jsatn, xtuqg oeh yni nyocinr gakr wwo ngewvuhdi nocewouk oy zpi mepxen dir pxuy vqoqfux — lud keza ix beor fajk kyix tiwjm!
Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum
here.
Have feedback to share about the online reading experience? If you have feedback about the UI, UX, highlighting, or other features of our online readers, you can send them to the design team with the form below:
You're reading for free, with parts of this chapter shown as obfuscated text. Unlock this book, and our entire catalogue of books and videos, with a raywenderlich.com Professional subscription.