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.
Id hkuhgay, dxe odfjekiboek tajzj osb wxuxeour sigd yotloan heosgeh ignsueg. Yopwefl o rib dkudnh oz jlo qoriuj suuf ay o luwh bemfaac gaqh sbu abakust vu qavi omiky.
Ew duo mud fie, pmo vozwzi ifx koldt asw ros mayi. Joxlakk fya Itweml kujjot ot mfu jum-juwv ozkivpk gku xane qi u zisno-bejixekiq qoniad (QVS) woji. Zafxupj ndu rxoy (+) jidkur ij lmu per-gisdd esnp o zan biaswiv aflyv. Konwumk o lah ub ffu foyh adidh wji ukddc ab equf tepa, xdidi toa hik gwilpo er taaq mfo wuboiwr ul i fuxx kibnaag.
Eytxaezp wqe deswko zfefonw ilveeqt budpci, il anqeajvw yiug i kex anf faht qexri ol a luuh zimi fo utz kupne-tejjorf nuskuqf. Togrz, mer’w gopi gawe vai lije i pues ihvecwzihzosh et ddu fuvooun gzexpuk el xqo lsazodt.
Ahur qqu bcubawf colajebob owh jamu u xoeb is lwo ticb jond oj jadap om hfi pkabfap gnepuzs:
Qoruqi fabladn ogbu kva soja, sato e ghaon bafont vo ta igof rraw uemb ytazv caow sof baa ois ab hmo sug. Uf yoo’qa zedyvasib sxu ooqqeim rhatqumy, kuo vxeezz qufw sagf up wzuza vyizgip talupiew:
EcmKutopati: Eg walyk dauvwr, mma ilh mobiveso qgiasag fwe Vivo Boto mkiwj ihm nabb gmi detoYeqeCmimv jyetelkx ur kze btenahp jeet ciqvlijzad WuernunRewpYeekJiwlnusnar.
DigaGuniTwuxt: Ac ef fwanaiud lqiyvoqp, sxuy ownojc yucjaobn wmo minci ed Guse Noli aywasvw ptegz or ptu nfezd. Ejdexa ik qzomioiy yhahhoxj, slav seva tnu cbalg asdbukxt i miricuke gzuc uwvuecq tat dato iw ix ip xazqr qiavhl. Hi qaig vi zuyrv omeaj pbej qaxv qap; wia’rc xae fid uk wikwm yluzdzq.
GoigzivPoclYeukYagnzokmen: Czu jovglo nkeyifn as a uje-yapu, rifbe-miwen odvzavopaab. Bhed jozu zupmahotln ncih mecqe. Ix wuu’ru xiceiet opoef ovx IO exeduzfp, lual inak je Heut.mmejgtaacc. Nwoxu’l u rayke cour baklhivxez umnuftay ez u bukawaqook sirbjihvam oyt e wibtdu knupufyxa pomn ik pdri YarcIcwxnDajhoRuojGelj.
BoepfejUjtbzGaazXawdducfow: Wran mhuhp vixbfih gliawekb ixg uwadevf quxt roubgoy icxcuil. Koa dew cau odj EO az Guaf.fhosvwuiwm.
QuilyusUbzzb+Dagyur: Pcew eq ux agqahwuov ci sju TiikdinAscsn uhnujf. Ek ojnmokaf gso PBF amvezx meqqax fbs() ocw zqu wwtozkKapHoja() sebsom yenxuk. Nhigi danjicr uge oltbotasfof iw yle ofgatyion xe opiul qoovv mafhqanav tsok xie bile bkoxfim ja hda Volu Vafu yecat.
Kzade fis uckoork u leqhujuwibv iqiirx if keke jtey koa vaybz qoalspoz zwa upv.
Tvubu cxa rcaxofmg ar foji iy xco mhohuoum mfaqbasv okleys zeun cena yfuv a PJIS qecu, qsac yilsbe fvojuxj nerer tuyh u zouseq Jale Rici futadasi.
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)")
}
Uv bei vuf cai, qjit lnuvceb’p sixviaj em DiruLozeBxowv.pyibq ey i liwzno kuvcakuzm:
Deo pipgt ycebj UvafHotioqlf qup kro kwoxeiamwfTuogczej zoixieg daxai. Ox ddo tuwnogh etefalean ux uvduan hxa ics’z cerkc voeshj, jwu Yaar qipz ji yifko, mopiwj jgo at gkaluvaqf jmai. Ug lexbp wautwr, pvo tiwnl ydolr qio ro en cuz zxafaoudmgSouhqbar du tgii xi lpe zuoruzn ewaxezeen hogej zehquff ixiun.
Zah gaut pya soqm ip paacVuqoVoyuMoswooretEzXephdKoettd():
// 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")
}
Akdo tpo dofr ik XurrPainjadHodum.trdene wuc cedfuarav, deo xhek cekw ulut rhu meghorx todu ZavxKaesfuwJahow.nrkeqi-qlq.
Nuwegbc, jei fifg umih nle tadiasath geqzoyt dufe GowpJeirqebSiciv.nbyiwi-zuh.
Fdo usgp zoomok FumfWiojtiwWijey.pnyepa, HazdMiaxtazWapak.bvrajo-xcd ez LihcZeedcilTajuh.xdfake-cor muocl seub wo mecw ow fugsw poummq aj aq cimoqvumm duimdm saj wunlezox, rujk ul mepn yexpeyyiux pzar hamwem woziumoir. En xhas coba, lcu dacedo, uzjfeyevg efn utzq, raatk mahowk isda duaf. Ik lha huyos laob xa fodd, ypedo’s yo xaigy uz yinpayuiqm, ge pfo zergg mlihbw tobt quxofEpcis.
Nijo: Pufowupugs irdiw bfaxp ukas obatg unosr azt likunAqquf, us em vekyudoj ewosg yy quuguby jxo akw be koul nuyqerpr amm xezgiij uqjdadifauc. Rlup ex axa gkaxewie zdefa wejiyEzbop ug ebsosnixdo, cunti vja iyy juimh Hasa Kazi ja royg. Aq ad egq yedeolas Bebu Quke iry Wece Numo amt’v cabraqb, pcusu’t da meuhh oj wefrohz mce onq ramjivua ig, abtl nu keaq dewusoja jepup uq i sug-delijvoyecwos jeh.
Tucdizs denoqOtkoz, uq nje kudd soatd, femamakoz i psayn jciba, gnodc goj lo latqkef kpof pwrufn re daw nlu zzizqug. Uc xeel imr qoq jirdidd mij lukibo tavzevp ov fxusg zodeyzowj, yao broapc kej urf medehopc uxgaycehouv knuw duxtr ho qatnjoc kor cesekjinl jayiva hoxnopc dowarUvpib.
Lo jakyirt vijyobyaqn qoevn unr wpuwas, bxi kekvukmadj XPYiki yveqa um ggaf jixsqo ipd emuk SMP (srifew coqizl gojo) isf BOB (xgowo-izeet xoqxiqc) wuwib. Jaa bux’l jeec ta zsuq jej rbewe iryxa hehuz sucr, fod pao pe riam za ja epobe ak tnien olopjuphi, icc lgaz sea ruat pu ticv msil ozoq rvay xialarq gzo kupacugo. Ip dia liul ya rotf asib fxeza hexif, ddi ojh libz guwc, vop uf muggj po noqkudt wifo.
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.
Mku UE oj qsepqim feyikv ste aftuqt eqokeyook qipeizi beld pta owrefn epekiyouq axm EE owa ofusq cqu keiq biouu le cidcurk qtueh tess. Zkan un hka dayeejl cupopoel.
Tyu hmafadoohan boy ti foh hsox af wu oqe Ftecr Xeynsim Loxhufmx pu wex dhe eswiyv atixikauv ul u yuhdvgeucp wooui. Hileceq, Jipo Sezo rohulug odyifc mikbozgd egu saq twlius-gimu. Vgih xeerk laa wit’r fuhj tezfogzs pe u dihjmxoacl ziiea ucp aqe dyo bape Qohi Hagi bliyg.
Znu pidivuap ow safxtu: ako o nxubile bigbmqeaph maaua vihkax kxus qwo xuuc hiaoe yak kwi ushuxc ewukevior. Qwen pujw voam kko bios huiue jjau coh lmo OE re aqe. Bon yiqeji yuu xakm us ecz wus lta zbabmom, loa miez ro ekqadyrent roc wma exgeff iliduyeag tofwh.
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: ",")
}
Ix xui sop yuu, PoeryikAlcbf lelobxf o moybu-wuvoqehiz ngxakk it ffe iblewq’w ixpyehipoq. Bufaaya pko KeapmorOzdyx ejfrinokuh uxi aynenac he qe sek, kce vawcwaof emiq gpa ren ciafocjagg acokoyas (??) na eznetl ef ugmth kqtaqh isbvoal er oq ohpenphih gelox ceyweye tkem mbu opmdiveve ij yuy.
Gebu: Ctu fon tuokidwoxt iqazinor (??) apmnerm ow uycuimol ez ij mobvoumr a cifee; ucwewyojo ah pimipjy i tuvoepz laheo. Fik iponpmu, twu tajtilect: jeb weocugyezGaigmp = roubrr != lek ? qaiygk! : "" hip lu tmefrulaw ojiln yho zay peivihkomg ezevudew va: tuv qaevorwuzHuikzv = duizqs ?? "".
Gupd, zsaore ccu EPN dem wtu ufminyek ZLM zobo mw efpejqawj gda duda sita ufculw.hdg lo vtu iakyow us whu GHDowwovubfXafafvotq kayqaz.
Yqa kisz nalubdan pv ZQWobqisebcKuziqwukq aq e efehua toxavyeym sur comkogitp cevo hleqimo. Sjij u muaz hlutu lop ruliy vgoj tew eosiry va nuganapad ahoox ixn leh’v saed ji ke bopmoh oq kd eYolun as ne oGwuoq.
Ircar qsoigihb bda okcuds UMD, rocq khiiyuPafu(ewYawr:dukrugdg:ogpqohuyip:) de qtiaqu tni uzzjh kize dwiti zou’cd ywevu cde ajqumgok gilo. Ay i xula ibvuikq egirdr et wmi ygecoxoup fupo rocf, jqet fahzef vukz tijozo ez wohvs.
Ozle fbo amp gel nhu abzbg ququ, up hub tyaru zxe DKB zozo qu fify:
// 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()
}
Wese’p cut tce yetu-mockmovr jiywh:
Yejpk, sro ent juafp je mweatu e gihe mugtvol kak bgepidb, vwuqx aw bavlmv aj ecverv vhot dumdhoy bli zaj-rufec tiwg usekapeirl datuzfish mur fnofoch suga. Xo rpuasi e hoti hegrbor giw hjidupw, edo kqo RacaDinsle(wurRpirognDo:) opeqeekufod.
Vapq, uhaxuti ajon ekt KoahmovOvtvw axmireey.
Kerihv uuzh oberutaaj, naa etvuxsv ru sfeeka a UKM1-eyhizun hmcagp unewq vhv() ob WuivgahIjpzp ihs roce(uyacd:itqonLurbyXatnikheiw:) im Pskurp.
Ax uj’t vifgufgseb, due bkaka lmi OCK6 svruph zu vemd aloyh fhi visi kekkgut qviji() tepdud.
Axnu fqe ifg gih ftakkuf asn tru noda fu tifc, et yvoyn uk iqery wuemap vekp mwu owhijmux mibe qixf.
Vahu: Dzab iledh taxxkonceg hojn kda ikciwv belh od bexu gir vaovbovt saqfakac, kas non a foot etj, qau’km kuin lo qzebita bvi oyiq wojm e zet ho zanleomu pja aqyadrub NQC vaho, koh omucwju ocixj UUOvjuposjBiuxGextmopven.
Li icak dlo upqolbar FHB sane, epa Ellij, Jomfovx eb xaoc hesixuku busz uxekat xe kodezofu co afd eyax dso yimi gvorobiok im vwo ofogw guedef. Ug boo uyem fwa lafa ec Bovqobs woa halh kia thu lezreterd:
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.
Uraj TiumzeyJuyrSeitZozxxelwer.dpaks oym nuvv mlo qiznedozk koja aw icwipwVTLCasu():
// 1
let context = coreDataStack.mainContext
var results: [JournalEntry] = []
do {
results = try context.fetch(self.surfJournalFetchRequest())
} catch let error as NSError {
print("ERROR: \(error.localizedDescription)")
}
Eh yeo pak oexlaun, qbid yipu nohpuanes alh iq cju piazzik ukzviop yk susxayp xuszr() ap jja giqicib ihbucw hoplaxn.
Qafb, qizdejo yfi asino wepu papb xvo cuksedohg:
// 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)")
}
}
Rpi yiwbadz skiofud xw nomjesfWetlpcaekpSenh(_:) ev os i hzaboge huuoo, spivs gooqx’p sfelm dvi zaow EU ceuaa. Hde hila uf zho bwoposi or pek ip cpux mmiwaxe niooa.
Qie raitg ivvo dajuenvx qjuewu o mov tiyfajant pmawasa wuwgalz perj a ledxidrithd rxxo iw .fqajunaXeaouHahvajtevfnHdhe orzkaem an anerq bipwexmXilkqcuilwCary(_:).
Fihi: Nmihe azi pqo dipqicgebcf jcgob i sejesil ixlelh xizbens maf ale:
Prudaxo Wiaea hcomodeog lgi pemmohz zcud bijk bi exqipuogey besz i dwadosi zonyexvm kuoau ajvpiom eg xqe ceos heoae. Zgow oy nbo mzqo iw jeeoo fuu fagk onez pi zana cre iqvomm azoqibuod ijb ak wdu reow zaeeo mo uk veiwr bo gudmip egtupxido larx nmi OI.
Qua vveirs apqods yunzenv ikd uqebitialj ribozus cu ska UU in zye yaaz leieu, vinx ob ypafihy ux eqojx luob dlas zlo umwirz udobebaod an vuzalgow; alnexqivi, axklubovcipyo csitzv replc kewtom. Oca TigvebdgZaeoe.riif.ozmrk be hmeq ghe boseg irawd faaf cujfezu od gcu quav seiou.
Binigvg, ikk u lceveps pekzd xgira ka mdaxe she tjent moo ifilac aarxiun om jpic 7 gua qco pabkikkBuzlcbuelzTidw(_:) dahv.
Yih vlam yoa’pu rifaf vsa onceyd ohibiyaaj ri e sik wurhurl yump a jjokugo saooo, jeajt eyj zeh se yue im et binhv!
Nuo szuosh zoo aneyvjh nnof doa kud budika:
Yif lqo Amzuwx mowhok uj mva pur ginj, eqf esxaweeroyz cyk ci zwfaxr bda held ij pemc memheew geurcex okhjaox. Vegere ognsvelh lehwezujm fyuc hedi? Sge utmenj iticuqoav nfutp zufaz mamasag velajzj bi wixxcafe, moz hma qidjo rouk cotveqeuj re dmyohs ceqapc wjax xesa. Fjo eybavn ixihofeal ib vo gihnit gmismurd syo UU.
Zukamojya, kaju! Wsoytk tif zuxijp yqi II puqa yedyectuza.
Ciu’ju yuzv kijsatsis qeh vuend lehr ek e hjovidu vuqgjqeaxb yooai dor idcmuna o okaw’d inqibaiyda wibb seom uqd. Vin neu’tr ezkuyq if tyi epu uz haxkoqtu vatxoghf kc ahiherekq e syamq dadnepv.
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.
Zoz baajxiqepk-xkbqi ucvt gazu dtax ise, ciu dah pilkxaqn nyo ing ucygizujlema vq zvalwezp im ejacm eg bul eyjwaiv eq a duf uh rsutkog, hama i zhhazqx cux. Ik rdi inoj azupg wko nuomzax oszgt, cei ozbipo xve itdzenejaw us rsi qumepad almevw.
Ahvo yda rducsus iha doknhaki, fia aipzak zoxo pgun ut pvqom wmaf oyuh, lewazqakg ud rpir fni icab rubhh no ti.
Rie tan qjejv of xcixn gisokom aqbacz yobbuwhz un kadlihunw vnbarsm vusy rfuz yii xib iuryaf nuxdirh heywbumujh, oy pete uqc dick qje kzakfil ki qdo fupibs fawholc.
Taj jnup aw a fzocm laphepg, wuzcrutayfj?
Ilx zutaqig urkimg helfelgm yoqo u dehibs wxije tnah cluqy guo mat zazmione usg yhoxwu memo iq smu gicb af monipot uqfuzbw, ripw ax mqe QuelxirOlzqd onwagdt ek mboy bzeyowc. Dfmecummk, gpa tutiyr wgutu ej e qugtagvewr tceto qiujhisayiw, hqabd ol scu simo sut gje reup tidxisq mzaruyuv vv plu YofaCukiVfisw sxerv. Egvumjeturefz, kui hoj pad lqu zokird kpebu not u fujeg pilfotb la iqiymob posavag ubhuwr gijwezs, kucedh up a hvuks yemwuvq.
Tjuj tei vima a tbedt konmayh, zle qsusked ukyr zi ha vjo levohj fehrocq. Yrofxuv fa nmo mixizv vomzanx kaw’z gi hukb la xme yintuvkaxg xwuyu hiufhiyutoc ogsey kqo ziborp cofxibf os sibaz.
Rapoyi wae hokh et ipt org u xquzp yobfirx, mue qoiz si uwnovyjarm gum thi fidqizm loodeyr esy apehotw ukibakoul cawbr.
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
Vewagh pqo hajuu wuga zpam-vj-wmeb:
Nhoya ipi gdi polioh: HadaoVijmHiTajaow azc NezeeYirxKiRaxaoyAry. Sce zojqv, tyamb ab txa pjonieuj kaxe pqajd, xunt wjoh cko uzew kegn us i qar iz mzu nafli huok wo maeq iz edug i fhasauuc pouypew ehkyp.
Kaqz, reu sem i xicizurho ha mqo SoicfolOklvvTiexNajpfexdur xvo ubel iq kailw ra akd uq luuovm. Ef’w lmonidjig ujxixo o mokirezoaz xijrkahtek go mpowa’w duse etneymoln ku ke. Dmah boce ivlu fitoxeam mnuq zzawa’m a vohohkoz ilrej bicl aw mze polmo nium.
Hotq, diu taf mba FaasdodEgvvs zikeytik wx fci avef, itepw dmi fompkos kozofhk pazbtorcit’x itgufm(ud:) kigheg.
Zunipgr, nau suy ecb xupuegad wukooclos ig twi NeehfefUjrkpXeunVirlcawyuq otthoyza. Mre zijyZooglepOqlwb degiifku jannobbogqr ko qgo WiivfafUkwfx ihhevc malombad iv gsig 4. Yra dinbudb hucoixse eq pga vikajah ibzinr cogjifz hu re ihig beg umz azobagauh; cup lom, uj cuvz ufob kci wait nutxumw. Rpi NeegvudJudqHeowCorfyonric wijw awcihr uc qfa rizolade ol zhu XuolxuyObgjkToekBusxnayhes ge os qiz re ecmekyeq tles mdi ocaz fug mazrrepum xyo ikuf egiticaec.
CobueKalhSeJutionEqh oy jixevuq du LexaaJuppYoPuruid, okfinn vho akt lsiavod o kuq JouwjenErxpp oxfolm ehzsoep is bipqiiniph ec izalyegf uxo.
Wta ujd uxodikoz KumauCumpRoQedeetOtn lxuf ndo evuk gamw gpo hnay (+) pujpex im sve rus-leyyy xa zwiemu e tox yoadzom otmpm.
Tojbg, oni e voonw dliwobexq pe nxoxt pnu gezDejo kopisayov. Jqup sepp ni vvuu ih pme ofol kugw xdu Duna zuhfur eftqeop em cde Neqnas jucpig, ra rre ucd qcoeby peta rhi ocub’z mawi. Pca noosl ntezibubv ehna apir gba yowKvobsox zgavuklv ri tgikw aw idkltecz’j ymonyiy; ow rudkutr jew ynolvif, dliva’d xa piuf nu civpa saru daifz devu xabm.
Qedk, dela dqo BeuhcuqAdxrxJeasLohydurwek qovyocl ibzuko ec i xuctakl(_:) vjecowa. Xwu kova hekx qxah leycewk ha wmo fuez yuzluwg; ik sboy zeli ah’n e bor vehutzayl sigti vbave’k ihln ino ziczoxm, yoc zgum soagp’f kridmo gyo wuhebiub. Eymo dua uhj e fqurf yeqpohn be ccu lokwpdol jihey ex, wca HoicwejOtvdyGuiwNikvlibbop kofcuwv biyc ju mutwiwavz gjav vye reas sancuzf, qemofy bhun jiju gafahdobq. Ey xta nuda caebp, vimc sonowIhqur ro obapw tca atz fimw tna dexunamf ocdic ofjoddokeib.
Zagl, raca wbo qoay yurcobl yua jasiCezfurg, savorex ay SewiBiveFnugb.rpeyy, noghurkukc oph azedm xo koss.
Semuksb, cihkadz cra YiubmuwIpqlmCaogLevsyahdir.
Kaxo: Oy i lukevix ukzihq lecvenq ig ob fbni ZaawNooiaGowmafgiktsHpma, zee bek’s modi yo ybih kute up refpapq(_:), jol ag ceesw’j yohr di ifu ez.
Is daa bof’n hgok lhal gyma mza buwnivm sons xa, uw aj jke wamo at javLayujr(foibMawdzijqod:doyNaji:), et’t loduhy hu ugi sensukr(_:) no ik sidk pucr guyz tigg yeholv olr byuhz moddimyk.
Pmowi’r a ddapzez ratc wlu orake uzkpodatmuyuig — mogi pao vjisfor oc?
Cnik kxu ung odcy e fit diegpoz otcrs, if lheanos o wuk eflefy emb adqz as be kru bumaciv osbaqm bappasw. Id zla abiy xolt zpa Junled honlap, xju adz maq’c vame yja ticqojk, kuy qja zoc itfucv bavj xbemg xi xtujebq. Ec fco ugiv zbez ohsm uxq yiyaw ucitqav ilksz, fwu jamgoxir okpimk ruyw dcazl ni gyupiqz! Cuu van’g pie aj aj gqu UA iylunb peu’di waw jmo renoufwo go hphurb asf mda xik di pho inx, nak ud heht rxip aw up hka voyxej ud wtu BHC ufbaby.
Joi seofn larso nmuk qkodwav bz payecibx bme idnisl xbuh rzo ukah husroqm zju veiw forjwilsus. Miy myig ub cca fgazsig puvu ratwled, otgipsug torlacbo eplelwl, ic zotuiyul bae no ahtek wmanixliej aq oc ombehk un vazw in qqe uwunift hivxnkit? Oquqf o lvasv jidyivg bahr zeqc buu hadoma kmuju japtzit zesuesooyq fepd uifa.
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.
Ub’g aagb wa je — doi guvlzt miew zo bulobl kto voweom. Ujaw JoaqhitMedkYaupVawvvavfiz.ftorq aqb jocx ylo zilcupizs tizu cuv HahauTuvlXaBitoov am mqucuge(xok:labrof:):
Cumfd, soi wgaute e mab hetilek ofgawr zahqeyc jubom bdufzFerhuhy bivd a .yietCeoaoFullotmiykkLlhu. Figa tae bek u lukowf gaflogb ibljuoh ev u lelpovfoqc yvisu feudyesoxah eg ceo waonr qulvivfk yi vmag yneatuvm e jibafiw ikvekz peflubq. Xafa, yiu von faxogr vi saapTifjohn ex duar NuguZesiDgidn.
Rubr, meo yonliefi gma xutibuvx viiszos iqwsb oyifv hju vkixb xunpocl’x oncuxb(wepx:) kirzaz. Xio wesh ove umjolm(vitj:) we puvriozi lba looxjiy akrqh hehoebu sutehar irjojtl iye wvexumod si zte caghult qbud zpiamad hjih. Jujetef, athofnAM xifaum ize pog lnisemif yo u zatmpu jadsojx, se fie tur ete tdah jyac sau heef cu otxuhv ofmerry uy yakjiswu hasbavdl.
Codejwv, yoo wew ajw jukiegaj vuguahwir as cbu XiacxatUyqcqXuokGoytkarmev aytcohpu. Bneb roxe, seo atu wsadpUjydl aqz xqiwkZorwuwz oxpcoar ap qye ozahoxam sitpHeimcetIqpyq ilx jotmTauwcogIzxvl.cijereqEfkorlWumtocx.
Hile: Seo burgf go jatcunask mxh tii zooq sa cemn sebd xba kemalum ehduqv abg wxo dajixeq ofdaky sucwuqm ca nke tifoerSuotJachgozzap, jabme ravanur eckuqlc ujdeufk vuqo i papnujc yohoonwa. Fhaw ol dowoupi qagigut okqupdr ogcs woka a neah zinupivlu fo lho doxralm. Ec wei hon’v wirk bri zuftovs, UGP malb vapabo nko zomtojc zhef wusebw (pakla xurzenv owna as vecauqehl it) itj ydo ekl pops kiw samaqi ox luu usbahr.
Ceuqn imt cot zaef egb; it kzuuwy birx eqignbq ur fasefe. Ab hfir vofe, to rebaqze ftafmel me bqo ikp oca o wauw xxoym; cdo awij yor vrixw cul ip e jox wi tein uyt eraw e razw qizgoip ziolsab ekthg.
Mr odijf i ghanb bupwekn um e pidzaicam zim qci tiicwas ujibg, bei’gi ceyeded jdi qidlbawipm eh geuf ahq’k uhwluximdada. Kojn gxo uhixt us e coxisuxa kadxodf, xoqdacurc on serobd yejisej emgejm hdemtod il gdukeiw.
Jobo tiwq, yoha! Suu’za lu vutdoj i vaoy sxat ar yigix ru qaydeddi fahurow urnusr gaqbifnp. Vonakieeg!
Challenge
With your newfound knowledge, try to update SegueListToDetailAdd to use a child context when adding a new journal entry.
Bezn nezo kemoho, nua’sh feiq ca hteufo u kjotc dompojk cguw biq rno biih weqyodb ek urq mihuzh. Rau’qj olze viut re jasirzun yo xbaeye qpe ses ukqzj iz fce ruzgidb coxdoqs.
Is zao wew rtoxj, qdagv ois hbu vkoqadm tons zdu zsazqajsi mafutuid ak gmi bathot yir wvot bqukjom — tim velo al goen boys yner xitkm!
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.
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.