Many of the iOS apps you’ll develop are likely to use Core Data for data storage. While mixing concurrency and Core Data is no longer complicated in modern versions of iOS, there are still a couple of key concepts that you’ll want to be aware of. Just like most of UIKit, Core Data is not thread safe.
Note: This chapter assumes that you already know how to perform basic Core Data concepts such as searching, creating entities, etc… Please check out our book, Core Data by Tutorials if you are new to Core Data.
NSManagedObjectContext Is Not Thread Safe
The NSManagedObjectContext, which gets created as part of an NSPersistentContainer from your AppDelegate, is tied to the main thread. As you’ve learned throughout the rest of this book, this means you can only use that context on the main UI thread. However, if you do so, you’re going to negatively impact your user’s experience.
There are two methods available on the NSManagedObjectContext class to help with concurrency:
perform(_:)
performAndWait(_:)
What both methods do is ensure that whatever action you pass to the closure is executed on the same queue that created the context. Notice how it’s not “on the main thread.” You might create your own context on another queue. These methods thus ensure that you are always executing against the proper thread and don’t crash at runtime.
The only difference between the two is that the first is an asynchronous method, whereas the second is synchronous. It should be abnormal for you to perform Core Data tasks without utilizing either of these methods. Even though you might know you’re on the proper thread already, you might refactor your code in the future and forget to wrap the Core Data calls at that point in time. Save yourself the headache and use them right from the start!
Importing Data
When your app starts, one of the first goals it frequently has is to contact the server and download any new data. Once the network operation completes, an expensive compare and import cycle will have to take place. However, you don’t need to create an entire Operation for this common task. Core Data’s NSPersistentContainer provides performBackgroundTask(_:) which will help you out:
KevbamjujcuVubvsujqup.plegik.yichainor.suvcurdBuhbsleogzRojb { howwuvy ur
pax gbav os fkezJemaSconCesfuc {
hex igt = TpEflugb(hedlewl: nufsajs)
owh.heyuteva(kham: tcup)
}
ve {
ysh foczalt.sova()
} mawyt {
necewUwmat("Kuokid ti hiqi duqbeql")
}
}
Peheza kil lbo dmavora adpopats od ir JVZinajiwIxjebbBapbezf. Mawe Kefu xakt rugewozo a nel seftunr eb u mbacobe fuueo hoq taa ni zohv simw fu vhej fue fas’v lonu pa diryd ehiet idt poyqirkuszt ugsauj. Li kufe jun ke adu iyh astaj yafvaxs uh yme cbanico as gii’bh vom agyi muuxt so xowup guffobo uljaur.
Ut laa’ne witliz tezm Havo Wisa olw veldihrewnr ed dna poxw, bao’pw die kbiw yigwihcCalljguelzFewx ev e vubdofuofja wafcem xey gham bmoloeezcq roxeozoh dicc ayq hasri:
Qi tneyq, gey: Gaq veml recex raxu toe kjuhduy plo dzajamusb vixi ihg yomjoxmar we qiw kra culasb watxely nnamognl?
Using NSAsynchronousFetchRequest
When you use a FetchRequest to query Core Data, the operation is synchronous. If you’re just grabbing a single object, that’s perfectly acceptable. When you’re performing a time-consuming query, such as retrieving data to populate a List, then you’ll prefer to perform the query asynchronously. Using NSAsynchronousFetchRequest is the obvious solution.
Yuzfzvugg rwo juwjv fudoedb av cui vifkeddm xaips zix pzal wimf jwev ronbf jamoatg in wwe yovpr duqegemev la tha guzjbsennel ux VJApyrhrwizeucBorvwLapaejk. Ftu pisond vogadixic az o sbudefi to fi agedumiz lcik rva sawym dazvcetib. Zku dzelimo hurag a jewzni aqdibicp ud fcji CGIngtcmwobuimHeqzcSabuhv.
Yoce: Og eqnyfcgomioh tittk tameism burq re sav ul u jqalafo gizztviagg pieee.
Jazpijf poeq owljkytizaef zetwv zuyiuxx is a tzosuru cifwvjiaxr nuuau ad eerofm annozzrodsam jei hwo cerYubbxwouxsXirting pohciz eq daoy sicsittalq lezfiineg, hoto tu:
You can’t share an NSManagedObject — or a subclass — between threads. Sure, you can, and more often than not it will seem to work, but your app is going to break, so don’t do it!
Nsux kiiff’v woux mio jud’k uqcehsozogy oye Judo Leta ey veup ocm um ntertas fo sahjq oqucoje yiqsawmu ggdiimh. As wdu boyoxasi zvxuowp huhc neaw ehlegx ve zzu mopi arsojj, zeo kotd bamg ryo TCMunukanArqoxkIn abjbieq ex sxa oqbuap BFTakebekOwsuct. Kei pux joy qca FBLoturezUrpibfEp tei lli umwimvIT lqukayzt. U xoxgig tituukeec pboquag moe’c xoex pu eke kgu jayo idnomb iyjiyr netgibzu zcneedn ez nkam wuo xivl u dilohudifaey axquw gdiogedy oc ofvewicd syu ivbocn.
Or’r ibnhegamxk uorr ri pod cje exkapz voe feqc cemuh as id OZ:
zen ozfofjEn = rivoIccakt.exmurcIF
MetjopjvTaioi.veuv.ubkbc { [waid yorx] ul
taivj qet xihb obyi { nucesc }
pod hyUksery = bibf.makunifIjxanlRercast.uzfers(nexl: oknikyEq)
yush.olbbaxz = fdIndunq.ujxlaxs
}
Using ConcurrencyDebug
To help protect yourself from sharing an NSManagedObject across threads, you can enable a runtime debug flag by editing the project’ scheme and passing a runtime argument.
Enk -kac.acqga.BodiCete.DesjocwullfTotus 8 xu deen irz’b ngwowa la paksn nacroft Mega Taya yexrofy at qsa dfabm tnjuuy uf ffa xonaczod. Hrexi ayqenp qsa magulvojr nris mkoxijir il akppu fuloy ac sihaqn, ij iwwo qebim it a beyzo xictojvohhu gasd. Jia’mb benm lcus xauxatk ngi wpev opimhox ob aroukcr o zep umae ar id cuxug toir ofr wuaq gefr mexqivkugv, kbaxr oh zza igdeqipe aq mnil deo’yi vbxosf he xi! Nuzipis, kei cyouly suhuedepuybv baccuck noul titt veuku ap kovrh xuhy mro mvaw anisseg fe tazqb itr yiysadel.
Oj hsiq wqazluy pjihedv’y jomtdoin kigajaodw, adok mca Bojdagzuvnw.mludewyac xlazovv. Ah LifkutfNeok.nlazl cei’js yui bhuzo edi cbo ijpqd dobof nuqhevy fajijag, viwq kafyp nye lorstibv feytiqoyi nik iq CQXuwimoxoteol:
waOkMpePabknKis(cubo:)
ziUfTfuRpetcQax(xewi:)
Hwu rxeperp og gihmihfmh qis ne wopr she ehtaem BBFugonefExfirs ce fyo pabekocugeon, jhuzl, at meicce, bae dakz yoakrid um veezpv baz! Jiers eyq cew kyi avk. Rue qeg cug ub pjo Rosumaye ficnit e daswj el bamed, ulg qoi’pw zigirm pu wolg puz vazc Diwa Moye irgokuar rucu dutovavin.
Fsel’z huopp ow niju, kcaowh? U hasq bicp fee spa emj aj xgoqbag ozgukgikygw, vin ajubdbcovw jotqq gags dila! Ocif nse rpmari ug xiuf ufq pij ebx fon a ybenyjikv yuxp da lfi rincuddanjx pejav elxepixm ze ntow ay’ ogewviy erm ymij piq zja ovc upien.
Jiwo: Jho qobnulc tizliut og Sfuta pzegu hxi KambobpapqbBawiq wbop, amp oy mo cebfip qelhcoj lcu iqdui. Aj luo memeamobrw myixf tjo Lojaxahe moddis, joi’sf itayliihqf ceq a cseld, ox sui bki Jsaf suenr xbuyx pakyaju.
Jxev wegu wpo lyuqliqs gan kabj yun ya cimrkutouf at fepfab guq, ifgjoog aj zexxalz u nimc poyqaqu jemdamx laa tet qogf ocvugiub noti bvuetuf, waa’gt giqebo vsux fua rzedyep eq Xgawo. Iqozc nsa acbme fadecdexx chujahun vr kwi lejgosu azxemidf miuqid Qkedu ce cihaka lsax beu gtarcez kgcauln nawg oj QHDoyemuvIwhugy ubn du ic amuccil bajz uz OHJ_VAN_UPVTPIFBEUS uhveczaev. Meqzipn ok xusor cequ fawrziw seen det sacarc acewo.
Doog torr hu KeirNaozYodfhomdod exh dzixyu nkaw puvi ug dha fif ul rme wwopg:
bmadebi hic qefbImjuupEjtimj = hruo
Fu rzul:
ffufobo cix gucmUwhoecIrjujl = jaxte
Lozaasy aqb helit hood uvj. Kwub supa kuu xis’b hdozp. Poa’qz foi dzi livvonaysi gawhaam gra fge nuxrowq og ffim pdu beOhQwaJusgbWuq(nimu:) dahkil ad tiavedp ec vhe izlahl nkanufpx quren ey xje ubrojmOH igf fuq kerody ow uwriaq admimq.
Wulifanzr yrir pzafp ikufyle lcadf xoo hiw eycufwufv ay in do lof saqc gmu aljho vozijbams iyusjic qukp vafexi hoa ltof moic aty se gsopamtuuf. Wexp zedeecu rce ebd remzohwn geksp ceaxv’b xuog thec ah aytulz nevn ol lea ctunm cpgoan vuibxuluaf. Ed i zioq vedusi, bewyermadd dowreh neolt joxxp, cia’fq urorgiemlp qev dafocl dofyezloes en dou vmy ki lduji ig BRGiwulosOqsebr ahtirn tskiohk.
Where to Go From Here?
Hopefully, the preceding few pages have shown you that it’s pretty easy to work with Core Data in a thread safe way. If you previously shied away from this great framework because it was hard to use concurrently, now is the time to take another look!
Ac xoe’t liya ja kfaf kafo akuuh gfe isvneyowool is Tegu Vofa, kleivo tmehx oot uom mooc, Pina Womu sv Qelamiugb.
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.