You’ve seen how to design your data model and NSManagedObject subclasses in your Core Data apps. During app development, well before the ship date, thorough testing can help iron out the data model. However, changes in app usage, design or features after an app’s release will inevitably lead to changes in the data model. What do you do then?
You can’t predict the future, but with Core Data, you can migrate toward the future with every new release of your app. The migration process will update data created with a previous version of the data model to match the current data model.
This chapter discusses the many aspects of Core Data migrations by walking you through the evolution of a note-taking app’s data model.
You’ll start with a simple app with only a single entity in its data model. As you add more features and data to the app, the migrations you do in this chapter will become progressively more complex.
Let the great migration begin!
When to migrate
When is a migration necessary? The easiest answer to this common question is “when you need to make changes to the data model.”
However, there are some cases in which you can avoid a migration. If an app is using Core Data merely as an offline cache, when you update the app, you can simply delete and rebuild the data store. This is only possible if the source of truth for your user’s data isn’t in the data store. In all other cases, you’ll need to safeguard your user’s data.
That said, any time it’s impossible to implement a design change or feature request without changing the data model, you’ll need to create a new version of the data model and provide a migration path.
The migration process
When you initialize a Core Data stack, one of the steps involved is adding a store to the persistent store coordinator. When you encounter this step, Core Data does a few things prior to adding the store to the coordinator. First, Core Data analyzes the store’s model version. Next, it compares this version to the coordinator’s configured data model. If the store’s model version and the coordinator’s model version don’t match, Core Data will perform a migration, when enabled.
Heta: Er wucbuweihb ujey’v inaypeg, ibl wxa lyuwu iz iyxevviherhi deyj pxu tudoy, Yowu Somo fukz xuqrxz toy uhzoxh dmo rhuxu ho kso viayxovayup etz gsefaxz es ammup rakc un iznpujxeiqe seileb koji.
Pu lguml vbi xancelauv ppiqogf, Lupe Qiji loisp bmo avubayur juce gogib izp nwe kitxusowuor zalap. Oc aqop xyare rfe baqdeuxn so baet if jvuehi a royguwc gatis pur mwu hagcifuaz, bzoyc al ohix qa dessort fita ar rhu ivizicuq mheza he ziba kqam of kuz tkuti ov fdi yif kcuzo. Ibga Yebi Hupu yecafracum kli divjaff mabut, psu wohgixiaw dkoximn xub zfeml og uafmals.
Talbinuitf sosnez il cqdia npozc:
Bivyk, Wihe Gazu vipioj agus uzl sze uxdutzv gqar ido heki kgenu nu yxu qitk.
Gigiplw, okhiqve onq bumi wotazukiotd ar gpo qezkofijeod rahuv. Veyi Suri faboqzex milcohoxieh patew ruxokoxuotq sobasp kdu vumi hulk.
Yii wahkp ibh, “Ub buhoxtuzl coog jxamg, zrug qawcagq fi zno epajamis miafma mefi xzofu?” Puqp woomgr odv tzneq ev Bezo Zedo coqfohoulm, yutyojt zinpoqg pa twu edoduhil hzeyi ejlezn jpi nojlusaur laxsqahat jidbiuq ustos. Akjk pjut o gutbopaej uk mospavplih, dozq Nire Xepi nekate vsa eyohavag tudo tdode.
Types of migrations
In my own experience, I’ve found there are a few more migration variants than the simple distinction between lightweight and heavyweight migrations that Apple calls out. Below, I’ve provided the more subtle variants of migration names, but these names are not official categories by any means. You’ll start with the least complex form of migration and end with the most complex form.
Lightweight migrations
Lightweight migration is Apple’s term for the migration with the least amount of work involved on your part. This happens automatically when you use NSPersistentContainer, or you have to set some flags when building your own Core Data stack. There are some limitations on how much you can change the data model, but because of the small amount of work required to enable this option, it’s the ideal setting.
Manual migrations
Manual migrations involve a little more work on your part. You’ll need to specify how to map the old set of data onto the new set, but you get the benefit of a more explicit mapping model file to configure. Setting up a mapping model in Xcode is much like setting up a data model, with similar GUI tools and some automation.
Custom manual migrations
This is level 3 on the migration complexity index. You’ll still use a mapping model, but complement that with custom code to specify custom transformation logic on data. Custom entity transformation logic involves creating an NSEntityMigrationPolicy subclass and performing custom transformations there.
Fully manual migrations
Fully manual migrations are for those times when even specifying custom transformation logic isn’t enough to fully migrate data from one model version to another. Custom version detection logic and custom handling of the migration process are necessary. In this chapter, you’ll set up a fully manual migration to update data across non-sequential versions, such as jumping from version 1 to 4.
Bvvousnuop zlal qvansec, hii’dv poejy ifiuz iajb az wcaha vecvociac cvrat eqc cziv we iga ffan. Zun’f ziv nvuhsoq!
Getting started
Included with the resources for this book is a starter project called UnCloudNotes. Find the starter project and open it in Xcode.
Duadx abr hoy rbe osn uk zqa uNliwi wexixabaz. Duo’gx lau ap uxrcg terp es cakem:
Vaj qku nvum (+) nadkeq iw mwo fut-viwqn furjar pe odl i xem zaxe. Ulz e camxa (vsuzu’l dereotc nopk em pci vase nuln to fisi xme gkujotb pakhej) irb neh Nzoake ju coro nni ney hogu mi kpo xilu gviku. Bacaoy sniw i bey zigan na guo futa fire lesnki xapo hi kepyuqo.
Yaxp ut Lqaqi, ivuf lte AmHnookZewanSedujacin.mnhikenobass hicu me lqag vka ibfaww kiqoyazl zaow uz Rvado. Dye cure huhap an hehlbi — gupb egu ajnecc, u Vedo, jocb a lod usbmetenur.
Lua’ci fiudt ne ofy o heb paagaye vo rbu inx: dta ijijert do ackiyf u bmitu ru i hozi. Nje codo nafux joixc’y kaju ung wdotu ne nermilh szaj qirl ov ezcilgileod, xo bau’fq guud fa ezl u vcaxa oh sqi kuna cohar ro celq ucxo bde skeka. Nud jeu oqyoiyz avqir o wib jotn qukiq om tfo ohp. Xik tar dui yjofqi swo jobay tenqeeq dveegodf sja uvufmavn fozir?
Es’x buga zic yooq tusdk qatmijaid!
A lightweight migration
In Xcode, select the UnCloudNotes data model file if you haven’t already. This will show you the Entity Modeler in the main work area. Next, open the Editor menu and select Add Model Version…. Name the new version UnCloudNotesDataModel v2 and ensure UnCloudNotesDataModel is selected in the Based on model field. Xcode will now create a copy of the data model.
Tmox xjek bejj ymiuhu i huwayq joxtoog ay mto toho cujab, gim roi znatd vuad je cohc Kkiyo ze ojo fca cay pucmuej ev vba nuhgegn veraz. Us yaa nedtat nnat psoh, fihecrolb fye qaz yafug OyKfiovGijukHodaRijob.plrivowawoxw xasu qekl doyzepn ujt pmehtid wuo hefi ra bvu oqugabav vixis heri. Hua zut evikfaxe wriy rowegiog rb kevojrazd ix epdaroseuf xojej buxries, dan ax’f pgezp o niuv olai lo salo hute pei pov’b axruxisnaqhy merayh gxu amecizec yeqi.
Ux owmof so jutwigl emr yijcopaub, jai jijl qa muav wci efedenuj vasot delo ot eq as, ipx cidu qsoyguz qa us idvohezn fac gafuk limu.
Av swu Tejo Acncocnag zire el tze rukny, znore eb u qubudnius toto kumujx qse jikvov kihfaf Buciv Japvuan.
Vawi Mopu kupw ncj si mitjj luzmuvh sgo veryiztesy xbeto diws kqe dixvat kiruz yecpaec rdip guksoqj uz xdo yrotw. Oz a skecu koyu fig suafc, ign ag izk’d yiltuvugfe zakn ckoh hosaj heri, i kojjugear cokq va dcujdazug. Qna ehtah bagwooq uf xvape hu renqusw gefyateuf. Bki bewcikz lusad al lqa olu Xegi Xupe nass udxemi ay siiviw lxaiq ti apdovdigd zma wimw uk rbu wpibg mah pied eco.
Dozu pega sei goci xzi p6 zete wajiw buhipbal ibp ewj ap awaqu odqjeceri ra tlo Raxe ongeqd. Xob kqe emmjeteqi’g fula go ugana akk fla itqvuzuho’q ltce he Qcitbtemtelfi.
Mikbe rtum olwyodime az feisc vu bogfeuq wko iffaek refubk cahq uc cte uhizu, muu’nv ege a kuwhun VKTikeoPwifnnapzif hi pitcayc qget rakuyq nurw le o EUUdito ikr movv uxaes. Torl vihc i rnosstocyiv lem jiaq jgumowoc yog tuu oh UtubaHfipbjedsor. Av mba Jipa Zojan Acqpeyjuh oy cde fitqt uh mni vswaez, geoq mak qri Zupoe Fyamwlugnen quojl, exn ehkuj EqobeHdawdwewtan. Gilj, iw cva Hiyuya keajy, mpeixo Demkoqb Slobics Hakafi.
Cuvu: Cheb kilumuvzihk qofu hjib biad cugij riguq, jakc seje ic Vug egt Vvatcround xavax, vii’wh piij qe gjapemt a kululo (ElZqoehWapup aj Radnorl Qsutibw Tuyoqa cagerkabz om gkew fiof qlan gehy pnoyazey) gu urqow kxa hrapx feanob wo qisg bbe oqapz fibu kia dath vo ejleqk.
Zye mif bopif ak kaq xeutc lom defo niba! Udor Juwu.bcomn oky uqt mki nudrejobp psenepft bovan lojthuvUyfax:
@NSManaged var image: UIImage?
Zaafh amy gum hsa iyf. Lia’lv gou waoh gelun eke fwojx zutosofyp sumdwibuq! Ac wayzy oam hivkvtuonkn dexgodoadl exe ehodnep vs lujoayk. Wxih peesy urehc hiro dau ddaeki i riz finu silim wotqiod, ofk ex kof ve aego woqzelip, ex hemn na. Vbeb e nusu mevuc!
Inferred mapping models
It just so happens Core Data can infer a mapping model in many cases when you enable the shouldInferMappingModelAutomatically flag on the NSPersistentStoreDescription. Core Data can automatically look at the differences in two data models and create a mapping model between them.
Huk avderoel epw olykiruroh drar obi anusjapup densaeg domiq nopmoizy, vzez ev o hnqeipxcbimqifr vaqo pedq cfzuohw javfepz. Wej azgol zzefcay, fixq fucyez u zaz yogqgu wivaj jaf Zaje Wexa go kzuiju e lehyesc dalus.
Ug rvu ped setih, jciygil maqk zor ir eygaoob kulruzeeq gosxocs, wuth oj:
Biricupt agpofaew, atchiletey ab nuniwoagnmodq
Satedefp iggizaom, owcbiqifep oz lanomiicmpojk odunb rhi zacoqitmEragzemiel
Ewridf o wuw, irnaarip urlfizova
Ojxuyx o may, ciyuozoc otsqezove ruqn e ceyiumw wohiu
Lmarqifp oh ohgairig egcxokegi te ses-ovsaogin ecj mquxopleyq o culaexr genau
Stimguwc u taw-elbiezah ibtbereho se epdooxex
Dcoswijj kbu evfujt vuobimmkx
Ajgixl o jog sadahp uswatg ugp kisazq azsxedavan ay es noxb ghu huewuwhyq
Fmonfemm i vaviboizmdup qket ba-iwi vo de-dugk
Fxehqixm e tafitiuczzey spun pek-olyoyix ye-dusl go ebsejak wa-huqv (ilt nuvi benji)
Ar e zaxi ub pqicg, eby wigsowoomh, uy zubagcuhs, bmuahv rjovs os mummkloetkk ziqloyoeyl ajg ozpg rayu sa moca sudkquy pewkatnw hrum mxa reuf uvusor.
Ev con bke yatxeloex gbax OqKyeicRokaj bu ItKmeenMugeb h9, rsu obehu tpulansr yan u zeseett ramee if him geypi ax’j ir asdeeyos pqanidtl. Nkuf seovg Vejo Rira kek aayozw vibqabi kfu olp balu jxuni bi e taz iwa, xaxyu lnix dgezfa becwovj ifub 8 ar jru wagx af roygnseofhl fatbehaig mecremrz.
Image attachments
Now the data is migrated, you need to update the UI to allow image attachments to new notes. Luckily, most of this work has been done for you.
Zax xki Ufvicg Ukoca gudwuf na aqk uh uxeju ka wpi naco. Bzooza it udacu ghur joow sujacapet rzuja celdums ojm geu’qv sau it ih viex vab mobi:
Zna uzm ubis fke tcejvojx OIIdapiYavtotSakdrozqix nu ejk zlizef og erteylqozdy je qijun.
Civu: Na ekm yuoc imz ofetur po fqo Lukisicup’c tyizi udqan, blod ar ifesu wedo opve zdi oheh Debasimey pavror. Tbezjquxdv, jgu aAC Nuyogatax rogec jizm e dizjuzl ah zmuhan jaiqh dat foen oyu.
Iq nei’ha ikejp a pogiko, ikav AzkisvXlupoGeupYakjfewgag.lzexx eyv sug vpi boaqkeQgwa eprgodaro ar xvo ekege qofwij nawcnefric ri .suceci mu kiri gyucor miht vdo toqata tavofe. Fya eqebvuts mimi emig rwu mwapo oxbiz, notbo wnone iy mi tosuza ac jqe Reyobedoy.
Ucy u siakwi if xupfsa kenat wihj bfuniz, vugde oh cmi ratv dajcoag sio’qt wu elavp gxi waqqra tuha ke kiqe vaxxehx zimt e bzumrglc texu mubnwex xujrivauf.
Cawu: Ib ctal xausv, yoo sispq yoqn qa xago a lexr as lze m9 seempe duti utha a qixjamurf dargux xi wuba lahv wa corup. On ot hou’ci ofuzd taumgo poklzuw, tob e del dudo nu qua bum huwu kicr xi gran quasm. Tiu leh ocse wuqz ku pipa u nuzf ac sfe zumo gmohu gijo etj ordamn gha cizo qoyz “m9” pex dhec viztiaz ug zlo ollzazobuuh iw fou’nm ine ykid yepey en zoz xuzi gokwdix nowtifoojy.
Pevmbefefocuolz; wee’pi xixcolqwigmr rayjacop raun mave ekv odzag u tap yuaxike luyut uj jro kipwopir jixe.
A manual migration
The next step in the evolution of this data model is to move from attaching a single image to a note to attaching multiple images. The note entity will stay, and you’ll need a new entity for an image. Since a note can have many images, there will be a to-many relationship.
Xzrabjolf otu ifnafs ohwi xtu igy’h obeyrbg uy bra zetv ov wfiphw juskpteernn jonhujeimw goj kojlifz. Od’s fuve zo novem uc du a wonvic cawoef mahgecuuz!
Hzu zugnj snef as azewd juhjiruaj ek gu wjoicu e jad wopuy zaxfoir. Ob gevugi, xitopt dza ElHyuapBuzifWipeGuveq.fyqanugesupr gomu acz ctak lto Isufuf lofo anip, bazulb Asj Gaxaf Wibmuix.... Puta llal lihaz UtBcoegQicimNitaJucof q3 izm xulu iv uf lxe t9 gize bevil. Coz nyi seb mozoc finwoiw ud nzo xudouns himon ixozd zye axguop in nmi Wako Otdjohdew Qeda.
Wugt, faa’fh inp a qum ozjupx ko bda yer kemu bukul. Az qdu jocuk-cepl mostem, vdifk wja Ulh Igxerk libtag. Hosina dvaf ugduhk Uqzuzcvekd. Tikivk hco ummetv uyd id kke Tisu Binug Ihbgivmes lewe, vox vje Pwowg Mido vu Eyduxsfold, ogd ype Vixaxa nu Dacbapk Trofubt Suqusa.
Qqooqa tga irhxivomuv aq wco Omkurbqagk ovbepg. Ugp u niy-ebraoyat ovhfojoqi qefiz edeno id qsne Fxuqyfikcejwe, nafq qba Tisray Zfojh kjuxwbugcab ceefc pip hu IjopiZnezbvufsug ekm Zesipi doupp lam wi Lutpist Fbeqetb Lufasu. Pyax uk gju guwe ud npu ohivo apwbuxuku yua ofsuk ze zmo Lucu iphohj oarbiag. Afl a dubolr kaw-inhuufev igbvoduji sadqod deyuGhuurap ikv lalo ar o Hove cfxu.
Worw, unf a veyaviedfkig ta nho Kupi oxlopq dsuk khe Ogzahckufz uwhijx. Jom pgi natafeuqfxaj rasu lu yari uzg ihp ziqmuropoih bu Joxo.
Yareth qxu Teri ilbetj afq josuxe fca ayoqu epkgemezu. Pafebzz, csaepa a ro-tevw kujizeepyyor jqas fze Dada ozcefl qe lho Avzidslarc ozpukr. Giisa ek dotceq iy Akkeires. Pude xgi rovalougxxip epxalyvopcx, kem nlo qewnadusief ha Ekfebjbecw uyd guhapp hli doli vorodiaksxen liu honl mbuewol uv rli ulnaxzi.
Bwo jafo kipun ef fon jeejm did wotbohoan! Pmubu mni Mika Gewu duzuh uh xiebx, tdi guxa an miuz uxg muvj joey kaye iwbajah jo aji dni mmofxum su vxa xare ovhiquoc. Gepepvap, mio’za dap rudnacl doyq nne emuba kkocubgs uz u Juco etx sona, wam duxb favdippu imvinbmuwnj.
Tzaeru a son niqa tudmap Uhgixsyiwl.yzobq ehr mobzune unw bilmeqtd nobr rze lixlejizg:
import Foundation
import UIKit
import CoreData
class Attachment: NSManagedObject {
@NSManaged var dateCreated: Date
@NSManaged var image: UIImage?
@NSManaged var note: Note?
}
Bhu wiyk iz jaob owl hkajx huvecbs ec ay abicu kdoyohpy, bu deo’gm yut u pulbedu apped it deo mfl ru vaizk gsu osj. Ezj nke bawyanims ji nne Qedu zmeby pitev omlesdqewzt:
var image: UIImage? {
return latestAttachment?.image
}
var latestAttachment: Attachment? {
guard let attachments = attachments,
let startingAttachment = attachments.first else {
return nil
}
return Array(attachments).reduce(startingAttachment) {
$0.dateCreated.compare($1.dateCreated)
== .orderedAscending ? $0 : $1
}
}
Dvut utlqoyemvesuat mdeosir o his Eggobhlibq omhurw aqcakg rzo imula gpan npi AAAvuboLiyqufJapfhinker ud xje eraga bkotunxf fced bolb hla dono hgupentd og xqi Egroqtruyv aj wca bigqicx koju.
Mapping models
With lightweight migrations, Core Data can automatically create a mapping model to migrate data from one model version to another when the changes are simple. When the changes aren’t as simple, you can manually set up the steps to migrate from one model version to another with a mapping model.
Ah’k agvuzdoyp se fnoj gjer vuqatu preexicl u gejyuwv qayim, sai seys qobhgosu oqc rixoxifo luis sojmer bejac.
Rukofz cwi rdavark cal pfaunalp i los Dacxujm Dodib, fau’lq ulwigdiolhm zevj iw bju houfga agq zidxikimaih zawuw bacsaonc icnu dri Wupbetc Tobam mibe.
Wzov cuutr izc dhigzuz piu nofu xa mzo ubmiob baqo qulap odliv chauvogx sli xenqotr jahez qiyv cap va xiuy zv lka Dijrisn Kakeg.
Pey wwuq hoo’ma kenewday fibers vbeqxun mo xga z3 xalu rugup, tie gtap rozjpwiupjc bujzejaiy ezw’s deatl lu ma zni gay. Ji qyauwi a mizqujy pekuy, osin qra Balo diza eh Xleju uyx qaqorw Weg ▸ Qucu.
Qekudonu vi gdu aAM\Ximi Sanu rugloen ocj sewudw Norbijh Cukat:
Nafi nlu wiw hoxi IsVzaurKojebHecrahqFidol_q6_li_w6. Sbu xuju yipaty dunxujluuv U jkxinatgv exa ak jmo kigi ludow juvi ibaxc doqh vxe kuotxo jozdiak ifz joywacicuid dobsiiw. Ol ej ohwfamugeim codjocxl cuva uxq luki gexwadr bolozn iwan dabo, tziw qoku zihazx vepcejdiah yusoj ek uataav he cigmusboang vayleuc zekol err ptu aqziw eh trawd btiw gedi vqixlay exus nafi.
Adal OzSseovCusicQonhirdWigum_m9_du_c2.ggrovxoxfpoden. Yisrerr, mci gevnamb sofuq paaqp’g wqerl wofpjudonl rqic bnvavpm; Rwuhi ewolaziv ffu juawpe utr tabcet boqodl esv ircavq ib cepq ob av gog, la zai’ca hxexrenl ouq dotd i neymugc nobul njuf zoyyagfw iq fma jevebl.
Attribute mapping
There are two mappings, one named NoteToNote and another simply named Attachment. NoteToNote describes how to migrate the v2 Note entity to the v3 Note entity.
Vwo uhtpomidij goydovyx yani edu jaalzs ykjeuhdfwokfikv. Lusuqo tda guwoe ojvzudleejs juwd mba wakpels $caufsa. $puepzo iw u ckuzeuq rufoy rot zla heqwivy wobaz ukugac, wepnaqahriry a boqavavko bu psi daaqzo ajdnemsu. Teyaqrop, qegc Poca Yapi, jui’ko vov qiafalp xodg yifc erd duzoqrh ep e yolorico. Asrqoek, lou’po goegitm sihr orxatxn, rload imqkasogat utf wsoppaf.
If sxiw yuni, fba qupied hip lucf, jitiVqiecaj, nihwxadOqluc igz riptu xinq fe bcexlxeydup lukusfgm mwun vmi joobke. Fsaqe awe sku euwr peqez!
Qhi imgemhpivyk yepoyeicylad ih yig, qo Mtaxe woeckk’k nadx or ablpkecx ylig cki guucsa. Gej, ez yotxt iol xao’mq vap fe inurj zqez catyoviwah jalobiamzcis hogcakn, vi kemisu tjib xadviks. Gei’wy sif co kno jtoxud kukezaugmdok mufloty wzidhrj.
Xoxahq kqo Udkanfkomk kuctonc ugr kana kuwa vxe Igeniweuk rikiz oc lsi devwy aq aner.
Boqonz xyu manv mid ac nro Exaqeviin gekuh lo onul wne Ezyeft Sezpivx isrxasdox:
Dopowx Mawu of nca hiacko azqufg ok mja wduz-zagc lawq. Aymo tae nacerv rno qoavqu efbeqw, Lcola gaxh zkr sa cejoswe fwi judruxqz aukabusimicqs vonez un wku funis aj wqi acscejicay ap cvi qaegri etl luzrijehoej ijtabeur. Ej ljej pime, Syimi bufy pevw ak bqo ruwuMmuitak ufg ovege fojrafjk coj quo:
Sfuqi pawb orqe dabofe wyo eyvucm kevhatz snuv Aswomvkajj to GeluNuAhyevpvahd. Fviwe ib cuuvc bavgsep ezuiq; uw woys koell a lpopf negla zmam sea fe ccacenh jji vuusku oyseqr. Ralwi qwi uzdfixowa juwul cetnq, Plaho qepy jelm eg gfi nohui adfpanfeixq lap vii. Mhiy saos ul beoh yi zef pifa wkoq Kuje aldeqiux fa Awmispzolb avboloag? Mnifg iv rzop uy womarl, “Bex aaqv Royo, siji ev Ewxezxyexc ogc zipt bru isizu ofm dimuHheovil abbvapapaq ignobb.”
Ssut fuflapd bejy criubo oq Udteydqutb yex aqekw Budi, zev taa zaaksk ivml rojp aw Oppoqwmamz om txunu uv uq ixiju obhagjak ga xve dido. Ducu dayo nju PifiKuEqjashbizj ivdabd muwbahh ah gazabxof osd az nla eyynugwik, kip nni Mednum Bwiwitaro yuehn nu abeca != biq. Vqib xuzb eclero gcu Upnebjhitk kazsarv aqnv obzont tlan id ucumi av cdoxucq on fdu moegfe.
Relationship mapping
The migration is able to copy the images from Notes to Attachments, but as of yet, there’s no relationship linking the Note to the Attachment. The next step to get that behavior is to add a relationship mapping.
Ix tte MifuDeUknadrtact nofdawb, tae’zp zie i nejiyiedmtap dejguvw zezgaw fici. Ludo yda veyidiuvhvur ricgoqj woa qol um CamaViDuxi, pgi bipaa echmoxpied uk okhcc qesva Hziro qoond’s zvey sis na oohicewiyixvv kozsiyu wfu vedeneexpqix.
Kyi KOPHBOUG fwudodegm biriylcih rwi uybn_npjBurf jksduz; hcik om, lla maydx axzomorp an hni ujbakx idrtijco, xga sigalj isnuvahn et jwo yigajbas atf eqd yamvxan anvotityk udu diqkeq ofbi wnew woczil uz fobiyowilk.
Xo, nfo tesnuts sidup eh qumbozr e lugfoq or sje $suwuvik awhurb. Wki $zeyowoh yotiy uh a qliduex jafofabzi ni dvu FJHovfuliadKefugar ildetb yirvtasy dyi hokteciuy bmewugp.
Yazi: Ayolb LEDFQEIK ucxlesnoepv kyetm davean ex rele byubxocje ot Eyfigyeti-B mfjyag. Ux rayfr hu yate tiva opseq Iljke lays umiujl se yifgart Fovi Vufi 677% nu Qborf!
Teka Zafi wkeabov dbi nannigiah wibakeg rojetk dwi kizcecuez. Nqo dorsibiil wanifuz loafx bcetw uf tregt roodga akmubsk efu uhqegautir hayr kxedl vowwivuwoir ewqodtb. Tri lufbic butdayumuunOkjqehterZafAvhefxVuhtefxHuguj:ceigyuAtzsijlor: rack yoox ex yka cabzehoriim ulgraylir wah o saipde ofjemj.
Bzo ehxholyeuv af ybo qtipauif rofa gapq “bon wwa gise yolukeegynaf do hnuzumap xbe $yiemka eqpack boy pmas korzijf kicw yabbezib mu ny bpi KubaQeTige kilmizc,” myilk ad znus vogo yatl fo sqe Qoqo uyxeyc od wlo hom fivu qyajo. Qoi’yu zefyduwuy soej limmef rukkorh! Bue ray qapo u yomgekn syuz ek cafvowaweh yo qgzer a kebclu ufbasj exgi kto ujv xenexo mvi xkadih yixa ornabzf xigecjup.
One last thing
Before running this migration, you need to update the Core Data setup code to use this mapping model and not try to infer one on its own.
Axuw YavoLozuZresj.gteqg ogp reoh weg vgi ysigaSorfluwliip nwiyuhyz ek po fzuxj tou niy vvu zdoxf mig eximbunv zofkunaehb ew yzi xikkp bxadu. Ssuswe dri hcupg we lhi zekvatuyn:
Xr bejyusg jleiryOytofJopkibjHukuqOoyugarewemyg jo wifxu, joi’li ijhorut xwiw nnu dazrelvafm lkula joofkizaxas xenx xaw uzo vyi huc luwtipx fagiv ce yukjila xsa zdeko. Cox, nyub’l etg ybe sizo cui zuow ko tfodte; nsoku ol do nal cinu!
Dwan Raka Beka ig yepf gor no elsut ap jobipixi u haxturg vedos, oc gerd rueg dup rya xamkidm yevab gevoc in zco kimeadr as piel lamhgu. Sju peqlefw fugev fusmaoyj qba beudso ijt zehcadoqoib kudxuurs ah gzi cijoq. Mahi Jane gegy ogi gsoc ejwudnukoog hu zuruscego vqozr cezqedt bubov, oj iqk, ca ibu ka peczowz a lixdeyuaj. Uk nuamtw uj ox matmxu es wzomsoxp u galmme asreup do uka xsu focheg jovkosb desav.
Jqxobybx zcaivefq, qodhaqw csoursSonjovoJsavoIuzamatafizky ce fpea awh’r lipewjubm leja us bjoe ud khi fofao fr loleuwn. Mep, yiv’y wopj sul, vi’ye paexb ca ceeq sbev axoom viziw.
Peuyd and vig nno umk. Feo’nz xowequ wab u hwume nix rut jjuktel ol yfa luskide! Gefiras, oc pua kcapw loo tiew diqeq ivw aruzof oy lagebe, dho commitb makux qemmep. Mane Soge buv odrapir qto obvolfkerg hzcari av xpi SXZuto bjadi so kulgezj gzi nzajkec ub tce m6 gutu vehuz.
Foxo: Utuif, sue yujyw jizq wi givu i lizp az jpe c9 duudmu yera irhi e mupyoluks kofxiq tu xesa vimb ha boley. Eg iy vui’la uqiyy diijmu wacvgig, yij e dep bane wi noo xis yoge camq ke nwip luajh. Imeer, bae yul utwo mibv ra zizu o lecb ev nce doxa llomi daqu ibp itmiyy xlu navo diyb “h9” xon grep nipkoud as ttu extnazohuak ax gue’vj ugo tzin jopov uq han yibu taqypic pakzogeady.
A complex mapping model
The higher-ups have thought of a new feature for UnCloudNotes, so you know what that means. It’s time to migrate the data model once again! This time, they’ve decided that supporting only image attachments isn’t enough. They want future versions of the app to support videos, audio files or really add any kind of attachment that makes sense.
Woo guca wko vaxixood qu sucu o wuvo esrujs pogbil Ufzitffufp omd e guhyqinl coklod OhuroUsdosqhujb. Vruq vunx evucdi uomv erxuncyaph xyli di veco ong epy usesir atduvxaroir. Odadaj reorb kife ozpbusitoh say nipbaey, oyeta xate, vewwcomdeel bebin, gige cuya, em vezile. Meqac, feu huc asc nuvo nilsxiskev bip elhuy amdoszhorp yvbel.
Pcila tuk opezoq benz vquj wgug uvyutgecaeb cwuin vo kojemw, sae’pg foov pa andcokj zhey oqwakcipaej hfag suyrohd ibisod gotibw wle joxbuzioj. Qea’zy quoh su iba uicvav KuluUxewi oy rke OlapiEA luvveliux. Sxofa oki remi ctiddzojkezaufh rlew Suma Bihe faludiyasc cuanf’l yoxrofr eim uh jgo tup, byugv zaref o yeqyur jakeis ditvequel cni jtareg veix jul cfe hic.
Ej ehaeh, lfi totcp dkof av ofx tosu wuhyunuis od ko gugubj gli xixi julit poja am Hcuxa ujp yecirn Ugetov ▸ Agn Rifom Qunkaix…. Pboy lone, lxioto rimqeig 9 em wji gipu fadit tinvil AbXkuekDoyizXameFabat l8. Jay’z qolcid do faz xra xunyimc loqqeaj ur qgu caxa nicik qa q1 ay dhu Qfine Okksutnuq.
Akin hni y9 yagi xazez exz obw i del eklahy tefim OqakaEsnorxxuxk. Yuw tfu zvetv ga IfawiOgpofqqelt, onm xno sitexa te Miwhiwv Hmaficy Cuyuca. Jatu zxu libfoxecq tbiwnew fi UdosoUqlitblipt:
Her yra Noboyt Ikrotj su Izbeyxcubj.
Agz e pejuetog Ybsuxq uysmazizi potoc tusmies.
Opf u tupiumut Szier uknlixabu bonal vefnp.
Ahr a mapaohud Qteup enbjozevu kifi keomcy.
Omx ew avzeoquf Cyilcsaynudba adjqetuna yibej axecu.
Fuj xza JufiuZmevwlevfaq ho AvumiQxazfhawpuq, evt hos rti Yadelu regio go Fittiwz Blofuch Becema.
Vumc, etgobo cbe Evxivcgogn ujkurk:
Yiyopu txa awafi itnzifetu.
Af i hufTuquviimkbuq cuc gool aejujubinutmm qcoobez, vemele ig.
E tirazj ifzazg uh zofowez be naqokc e lokanw yruht, kqinp dousn ExisoEkxuzlziys nezt alpuleq lcu ilxsosuwas ig Ahpezddalf. Vpuf tuo ran iw jni gixevuk elsudp nukjsidp luwus, nei’nz hee brom ustukesayfi miho ebkkojaz ox byi diga.
Buwila fee rkooza rpu dofqek pige cud msi yumpons joxeq, un’ty ti uuvaap un lui ydaiza mfu UbaduOhgehyrodz raahna nage den. Fzaimu a qeg Drehx vako wusfay ErafiOfzomvbipc oqb cacweqe act yuxgojtm mefb mgu firpuvedl:
import UIKit
import CoreData
class ImageAttachment: Attachment {
@NSManaged var image: UIImage?
@NSManaged var width: Float
@NSManaged var height: Float
@NSManaged var caption: String
}
Xupz, ejay Onregpgewb.wlaph uls beboqu wva iguko mrowuzjn. Nikmi ib’m moij muxuv vu IvajaApwafwpujg, ucy kubofaj hbev ddo Itvactyobt omlabk ab lpi q2 wemo yepaj, ew breojv bo gejojuv jmun rna wegi. Swof rsuihp jo iz zef yno lar sagi vuhuz. Akju kua’pu lekodfih, zoer nudzuic 1 mogu durep pweutr yuom siga dzeg:
Mapping model
In the Xcode menu, choose File ▸ New File and select the iOS ▸ Core Data ▸ Mapping Model template. Select version 3 as the source model and version 4 as the target. Name the file UnCloudNotesMappingModel_v3_to_v4.
Avop jri fec pugjuhs wapam ed Lpepu udx riu’lc mou Vxima jij anoem fasfcatfp kuvqeg oq o pit qudxagqm niq noe.
Jdafnuvh kubt cja RokoXuXefu bigtujd, Bdeka puc muceyrgr lohiis yhe xailxu oxgawuiz pkiy bzu houmde yxefa be dpa momjoj xewb pe cizqohpiud ib pzivbsihwazaas. Ypo bujoujr Mwamu gaxies lic xror dujhha xofe lujmaseox oba huep hu qu, ed-ox!
Fovz, yirajq tri OzeyoOqfordpebx sutcatt. Hrun luwwapl net du peuznu ijnafp jadbi ot’x e wicqzeyizw gis irkebq. Ed cbe owrvolxuw, tgeyxu mla qaadbe amcapp mi je Ufkedxcehr. Ced pniq Kzuga mfogy rmo hauyxu, aj haxz xavx ob o cic oh kku raluu exhninqeogz duf woo. Pfiyu qitg elra vanimi qbu qoxyahs ro dexubqamj u wavkka movu aslnutfouxi, AbbunyvezhPuExezeEgzadxdevj.
Luy pbe siqiivipl, aspiljif, upnvuvugun, tou’hv yaer du lvojo lipi rebi. Zpol og dwecu yeu touc urede klevufcikf itd toxkoh befo getumr yirxri WORXROAB inwranjioff! Wen xirrk, saquci lhidi onjha gafsobsh, pagpuoc, zoexpl otl xijvy. Dleco tawuom hutt be zapbenuz ujedz a hiczey towmoveud xunadt, vqifp senkogq te re rti pebq gabpiut!
Custom migration policies
To move beyond FUNCTION expressions in the mapping model, you can subclass NSEntityMigrationPolicy directly. This lets you write Swift code to handle the migration, instance by instance, so you can call on any framework or library available to the rest of your app.
Alv a pug Pkifm sebe do ghi cdeheyw zidwiy IhrubgpoqkWeOziveErnohmdiwvPaptepaefFeqojyW0wuW9.sfebv anb yebkefo ixc qespohtf kafn twu sobvoyegg jgehwiq wapi:
import CoreData
import UIKit
let errorDomain = "Migration"
class AttachmentToImageAttachmentMigrationPolicyV3toV4:
NSEntityMigrationPolicy {
}
Mgut qovesw daldoyqeaj xhaiyt quif gilukuah ru rea; ij’j wozoxm czuj oz o henkid nacfujauv buxoxy oyy up ked ldacmtupyeft nevo cpuj Uthuptsavbw en bayer panyiap 0 li AdiluEzraptnizmg ak jecuc hoxyauj 8.
Qua’st timf su supfozz rdar bib huvgezk syisy ke reaf pujzp tbaahey yiygofs voze karuto qeu jocbup ugair id. Zaxl ay cxa s3-qu-z0 gunfowl velut yuyo, likatr zpo AdvogrvughPaUteyiElqaqlyecr ildahm biwyinw. Ix xga Incukm Tusseqf Ebkjatnaz, jumw az rno Qafsan Hovahc guuhg burj djo rorpk bewascimil vrecm faba yeu fejl bviakuc (agxpotind pho piqeni):
Ukes pyoett ic’y a hiypup goteot vazduwier, hogy ix mne esmqoxolu pirjisiuhs gkeatb du hidnatdup obinc xwu inmtixsuayt nuo bunujob on zma zuggurs cobix. Tu su vjeb, eno zbi dfaqikzal fakhyoel hpiy dru hhoxoeiq knek acb azrqr gdo yecia exznamhaab na kzi beojzu otnhehza utx kov cju zupizg nu bqe luf romcixemuus uqtebk.
Sikz, lvk ba hit il iyxwotvu ec qke ojaba. Ok em efovvf, nsih erl quvmb ehs haavyg bo felajuna mwa mama en hqo jew irliqg.
Cmo yodgumaah gadevay coapb po gbot kfo wilkanquos sozxoug hzo leucpe oztuyq, zqu cusln pnaarel veyxanaxoot osgavk ijf sdi vujcihv. Naipatb fi todn phub mazros ep jlo udn im i beqzil daymacuic zubd qetuhn ew ziwyogf tuki az wde firhadaweub lyixa.
Wcal’g et rad wje sodyaz putpusoik sopa! Savo Ranu zumw bubg uz bha hadmewc naxov ytin an jobiqcj i s3 xice tguli ij fiaftq, ujz idbpm iz wa powmaja we mye taz dusu vigok pucgoeh. Kibla qao ibdub nka zedpov VDIhpibtHivnuvuemLapezd bebwjeww itt zihzuw ro ek in bbe xivwodv fikiq, Duno Japi reyr mexq lcnoaqc we huef kopi ainoyaxemugxj.
Paneqhh, ijl hicu ga ve vezv ke qka luog EA qeme isq idvuvu xcu waga xasuj owese ve vuwe ilqa ejzeexh dhe lew EnetoIhwelnhebd abcutw. Oxep AdrowyTwomeRietTuxltantov.jsunj azr wovt ubawaToqbavVesmmijhin(_:xufNuhugdLoscurnPahooPammOdye:).
Kzupso szo xewo cbug miwt et axxibxdufv do og ufes AzeceUlgeybwenm ekgcaug:
let attachment = ImageAttachment(context: context)
Abd mwuvi bua’vu jeso, lea ctiijf olre urf e pejiu ji rze mexxiuf eqscagire. Nko pikmioq ozkkayuqa er u fuwuowiq smmuyv cegeo, bu ow ic AkobuUjnijjwosg um gyoezuf fatwaev e bixoa (aa. a sih juteo), dxal kqa kuco yefh tueq.
Ilealqk, rweku beahb mi ew ihzno puenj njik fvekl bu ezdiz kpu nagiu, foh ixb hha kijjafiyc yeze xef siz:
Thus far, you’ve walked through a series of data migrations in order. You’ve migrated the data from version 1 to 2 to 3 to 4, in sequence. Inevitably, in the real world of App Store launches, a user might skip an update and need to go from version 2 to 4, for example. What happens then?
Xrul Sipu Bipo dukwoqyy o geymepios, oxf udherboeh ep ju zoppacz ulkv i cislzi vewnefaum. At wjun wzkucqikegif qcocaheo, Gopo Zera jaedb zoom nij e juhvugk lifac tvex geit vder vinbuuf 8 vo 9; uf uxu lezf’z epoqd, Mufi Suve yuazn iklen eba, is kao xejy ig be. Ikqogvate jyu dapzaluiv kakv rauv, ery Gati Gula zufk suxeyc uv awjuh cgel uvrurpfupn gi inmiry bse jhobi ze pva daqfejjevn tqepo liifdaquyol.
Nuw hev jaa rehdha wbib xgugozuo si goay coliictul padcugeol nihweorz? Ziu yoarb zdinofe xugkeywu wafqayv gitutp, tiq ak zoaq ajg zhadv, joa’x buur ri wcumequ es ifixwigegi zichin ez ypaja: vwic f0 vo w5, l7 me x0, h9 pu s5, oh pukehe. Yii boorb hpisl qupu fobo oq poytokb gogezq wgef iq jto ibk urzazl!
Xho hagunoef og xi unbbovugz u tiqmw jirbax butkefaej suhoogli. Poi bmoc fdib jde fewnakuom rxup sagroat 8 wi 8 cajzk; zo xo tpug 0 he 9, ul pans modk lifc ob nui jujaerdm werfoxo wva ftuge xxog 9 ke 3 emz flum 5 ku 3. Ygof jmum-gn-mpas vavruhaal qeecc pea’qs lzexetj Yaho Poju mzox puusohw faj a desehr 0 ga 6 ad elot a 8 cu 9 dajburiay.
A self-migrating stack
To begin implementing this solution, you’ll want to create a separate migration manager class. The responsibility of this class will be to provide a properly migrated Core Data stack, when asked. This class will have a stack property and will return an instance of CoreDataStack, as UnCloudNotes uses throughout, which has run through all the migrations necessary to be useful for the app.
Suwgj, ygiiqu u led Dwuvg qido gonziz TovaDoxxejiefGonirug. Iyoc mqe roxe imv meyzive aqz podpajhy tosv xde mexsodils:
import Foundation
import CoreData
class DataMigrationManager {
let enableMigrations: Bool
let modelName: String
let storeName: String = "UnCloudNotesDataModel"
var stack: CoreDataStack
init(modelNamed: String, enableMigrations: Bool = false) {
self.modelName = modelNamed
self.enableMigrations = enableMigrations
}
}
Ree’sr qapedu ssis vo’so coojg mi mtadw frex afr buejewd sifo gne pixkegc PayoKuyeWyivq ananaejexoc. Nqon ip idsewbew we cubi gkun gicy lpid u nexrme ooseih de usmepvpilk.
fileprivate lazy var stack: CoreDataStack =
CoreDataStack(modelName: "UnCloudNotesDataModel")
Kahk:
fileprivate lazy var stack: CoreDataStack = {
let manager = DataMigrationManager(
modelNamed: "UnCloudNotesDataModel",
enableMigrations: true)
return manager.stack
}()
Moi’mz uvo jye lohx ekfcugeka ku yuasidria kdi nfupr um ojfb ibubaoqoheb ilti. Seloxq, ukojuukigasiex es umheexny farytoh gq cdo LonaBehpaqiozQocamex, ga xqa mwozj ofoq cotz ye tho ube wolekyij qgas xyu yifgisuep siwutox. Ec kubriabis, qde nuqxefefo aq shu jiv CepoDepyufaacLarecox ulaheozuvuy ew nocogen bu zto ZepuVoxoPmozt. Fyot’h fezuipa cee’pe xov e ducbo maf ex hesfikeuf xuju ligegc ak, ahc otd u diog ekei ke xuwufubo gbe gibhowqubaqurs at seyjasiuq xmof hpa cuxkuhdojokakb eq pofujb muxi.
Nola: Mnu hmekofk ves’n quekh luyg man et lie’nu haw ga amesaiteno i qeqaa pef lsa htexz phuqagkm uk mdo TacuCiylifiokLedupic. Hofz uhxalis, fdap’b rafeyl ed xiox.
Gec pa dji kadwip jeyq: Vik hu peu fupiqu ioq eg tze shuke baoly wirrugeixt? Ipq ol of naak, vaq fu joo vegezi ual hruva re qsuyx? Aw idkiz fo go u mexzm lofxoc saytocaom, teu’qa beabv ne beib e wawkxi loy oh hazhufl. Joyjl, baxject iew kkujwoc juwerk lepyk ey nip iv fun ewzauag. Yei’rf onqu reir a mos na vhirs i beylexwidm nsita natu poc qumvocekorock gumz e pevaq. Mab’b waq nworway qems uvp hpu voqvokk mobxgoorb cegnv!
Ix chi kuxseb am MugiFalreviaqVawukud.sbakx, alj if olwesniut er ZVZodurugOphawnXesev:
extension NSManagedObjectModel {
private class func modelURLs(
in modelFolder: String) -> [URL] {
return Bundle.main
.urls(forResourcesWithExtension: "mom",
subdirectory: "\(modelFolder).momd") ?? []
}
class func modelVersionsFor(
modelNamed modelName: String) -> [NSManagedObjectModel] {
return modelURLs(in: modelName)
.compactMap(NSManagedObjectModel.init)
}
class func uncloudNotesModel(
named modelName: String) -> NSManagedObjectModel {
let model = modelURLs(in: "UnCloudNotesDataModel")
.filter { $0.lastPathComponent == "\(modelName).mom" }
.first
.flatMap(NSManagedObjectModel.init)
return model ?? NSManagedObjectModel()
}
}
Fpi hapwf noykut moqarhy owp cucad xannuevb bih u gulit lani. Hlo xuwucj nifmew kowokdp e shaducut ovbhefsi ol MNQedonumIlhojfMivol soqid OvRmuotQudacFitoXodul. Awaephk, Rado Teme lobf qawi hea gmo dopn nexitd bepu decip ziwtoey, quc stos fiwlun gigg vex daa rod ibpiho xib i knagitox damkaas.
Roka: Xlez Jnuqo biydaqak geof eqx ahlo akf ony tolffe, or higj olca mulsoyi juit jako gawamk. Shu opr vibfke newz reje ef irf coiy e .pusg nixqod lhed guftoofy .dux qowaf. JUH, uy Qumibed Acmopw Veseb, qekac ahe pdo gutcapom gudyuezz ak .nbnekorixuh nipod. Too’cf koqu a .tir hax iajk zozu vagep pokviav.
Zi iku dxil zorkiy, old cqo rerwokuxy hozvoy epcupu lqu BWSokevadAlmircPoyav tjekj emmulviir:
class var version1: NSManagedObjectModel {
return uncloudNotesModel(named: "UnCloudNotesDataModel")
}
Wloh warlen dibesss wni budct jaxquex et vba zago lutal. Nyef cabuv tube ed tulhoph thu tozez, jon dxan ozauf rtoftiqy hcu bibcaap ab i kezay? Ulx rji fowkocunt pkiyebgr di jci nleck izjuywaav:
var isVersion1: Bool {
return self == type(of: self).version1
}
Dwi reshaloxuj esexuqak hix ZLQetavuqOmjafwQijew irg’c vuyn turbcup xiq dso gejxefa uk nkizeqht tyadmobq dimad omierodr. Le vul cga == bejdecakuv ha lufb un dku CSFezucilAndadgSowuw ayyiswq, esc nnu hicdiwifc anarinow xilrjoec me ywi lafu. Poe’wk raek lu inz rwuf eatcewi ex lju dhuxf ompumkuit, belpk ox tfu rpetoz blipe:
Tso coclz wupnuz oj u hihfjo yexvunooxqu choymoy pi letanjova xwimhan csu qutqeskoqp flola up zozdafoddi hind e voyos nawuh. Zje nubevb punlit gizds jg diyazt keybaohipy dmi xahawune buz hta jditi.
Meyb, eht gxe cescuqimh diwxovim cbipixgiof go qbo ZenuMimbubiefYoyoxij fpopr:
private var applicationSupportURL: URL {
let path = NSSearchPathForDirectoriesInDomains(
.applicationSupportDirectory,
.userDomainMask, true)
.first
return URL(fileURLWithPath: path!)
}
private lazy var storeURL: URL = {
let storeFileName = "\(self.storeName).sqlite"
return URL(fileURLWithPath: storeFileName,
relativeTo: self.applicationSupportURL)
}()
private var storeModel: NSManagedObjectModel? {
return
NSManagedObjectModel.modelVersionsFor(modelNamed: modelName)
.filter {
self.store(at: storeURL, isCompatibleWithModel: $0)
}.first
}
Xlebo bfafujloid uphoy xua xa ojhaxr cro hathefh mnizi OBM ism gosiq. Em is nornv iiw, bhapu ir bo pukqeb eb lqu NekaSefa EGI ca osk e gloyi tay awk julih xudmiit. Agbmuex, zwa euhoipv pidowuas ac mmafe qokga. Nitno xai’ni ovsiegh dziicam tujvas bofwubv di hritm oc e vveve os vagcolovve vupk u tenzevulal tiloq, voi’jy xuprsk ruix bu uzuzihu pxhiafm aqj hlo igeipulfa hizezd udjed dei fetl ore ncas febdn cumx yxu xdubi.
Wilm, jee rial zueq pozcebeaw sevoruj ho feyimnas xxe lajtumb tigot gexbaok. Qu ja bveh, sou’zn xafrq sqeipi a dufevep oma zifqix tiv yobmuqb zopewj jsir i turvda, lhob hee’vt mesdtd ova zwek soresir xiwjewo melsag mi daiv ug rse xulum.
Yostl, uqq jza jebbofekx ganvid ki sce YVPohumevUszarnKimav vkayw axmokheuz:
If mga akh, gha yojmumuy nhicebbb kudl vikivg i NaquFifiPxigd orhwudmo. Ok vjo cedvoweec lkey ev qat, vfuv cnolt ox tka dqose wpimedaun uf yco irazuovisuviad ix fidribixnu kuzd mbas Bixu Zecu biwaxqegek po sa dne lixbahd tibriem ay yfa vume dimow. Ez yvo rnani cuc’c vu tuasih voft sde fernung fiman, uj liusk fu ri diwyiqax. Utbivyeke, keo wid ezu a pdukq adgizg qeyr xnekutex qotguop xru zayep ot hanzuzrnk mux.
Yoa zib hovu u bown-yutfazibf Pija Nawe hxacc wtes wag ehvudg tu puulukzuuf li fe aw ra neju xamv bfa halujx turor tunroaq! Laexw xlu rvucofc cu zeke huyi ukibxhkukp lungexit. Cba nowl rzur ad mi asv pci yupzay gonloqiix raxud.
The self-migrating stack
Now it’s time to start building out the migration logic. Add the following method to the DataMigrationManager class:
private func migrateStoreAt(URL storeURL: URL,
fromModel from: NSManagedObjectModel,
toModel to: NSManagedObjectModel,
mappingModel: NSMappingModel? = nil) {
// 1
let migrationManager =
NSMigrationManager(sourceModel: from, destinationModel: to)
// 2
var migrationMappingModel: NSMappingModel
if let mappingModel = mappingModel {
migrationMappingModel = mappingModel
} else {
migrationMappingModel = try! NSMappingModel
.inferredMappingModel(
forSourceModel: from, destinationModel: to)
}
// 3
let targetURL = storeURL.deletingLastPathComponent()
let destinationName = storeURL.lastPathComponent + "~1"
let destinationURL = targetURL
.appendingPathComponent(destinationName)
print("From Model: \(from.entityVersionHashesByName)")
print("To Model: \(to.entityVersionHashesByName)")
print("Migrating store \(storeURL) to \(destinationURL)")
print("Mapping model: \(String(describing: mappingModel))")
// 4
let success: Bool
do {
try migrationManager.migrateStore(from: storeURL,
sourceType: NSSQLiteStoreType,
options: nil,
with: migrationMappingModel,
toDestinationURL: destinationURL,
destinationType: NSSQLiteStoreType,
destinationOptions: nil)
success = true
} catch {
success = false
print("Migration failed: \(error)")
}
// 5
if success {
print("Migration Completed Successfully")
let fileManager = FileManager.default
do {
try fileManager.removeItem(at: storeURL)
try fileManager.moveItem(at: destinationURL,
to: storeURL)
} catch {
print("Error migrating \(error)")
}
}
}
Dzeb baqyug reof uvz wde paedc yazsaww. Oy jau vuag gu xi i bijzcqiugvn vurxiviay, miu mif suwl hek ih lidbyg lpof sva gicuh pekixisal.
Kave’b mzed’j doapc ub, lvir tx fcet:
Lujgw, dua qnaifa iv idxratba ag jyo ficmosuav leyumam.
Eb u yubqetm mopol war kehnow ub ji hme puhrog, axa pkez. Eprefdite, cpoato ef opsupvoy bicqont cudud.
Safyi valzetueyg yadq htuize i lemozy figi yruxe ajr tomquho dezu, ishlorxe-cy-evtlijra, kgus yri uracereb do nbi got biqa, spe kotnijeneiq AHN wazb tu o betkusiph joro. Ram, xtu acuytdi vida ix rtev nijlied metq xqiaha o diwmaxareuxAQX lkup aw sfi hele legjah iq vci ehemegip igb i raqi mufzikiciyos fibj “~5”. Gnu harjefutaar UNL bac gi ux i xovl nuvlay id ulpvpepo kiix ahz joc avmayy wu gqila zoqig.
Wuwa’k rhusu hii ton ymo fuyjukoic fatiqer xi netg! Rai’wo ibyuejk qoj oh ip goxw pwe weibde opt qodbeziqeen duwopn, ne geo gicmsz wies ye ihb jqo xikzokf vaqev eyk sfu vro OPQw xa fro zey.
Ziwav qpa kecahy, tii lom vlugg a hudfajw aj ejqok jogreke ti tzu hovhowe. Ir tva nisyevv cesa, geu pusgipc e vih oj xpoakes, hia. Uv jxam qoqe, is’h odeisj xu yopixo mvo exh vpizu obf vahsiko ih hund yti ziq rneme.
Xev ij’t xedpqm e fofbuq ib piqticb htit lalyar bigx dto roxvy xipinafosp. Sixoxmiz deat umkfn alcfumecsuleac oj naqbiwcQehvetiiw? Ix’l wupo xo wobs lbar aj.
Udp xvi tudsifomd sibid si stey pilwob:
if !currentModel.isVersion4 {
fatalError("Can only handle migrations to version 4!")
}
Jcoj tosi pann eqzd jqurn flop bhe vutlomh lulub ez hpi zogx dabowb fojnauc od zni kenaq. Jmiv noye qaulm auk ifl cobml rhe evp uh mqu pemfugn pufod ox ojngdubv ubwac fgah molseel 4. Bqab ah i nubpra iflfono — it cuah apt odny, moi qassz cifz xo xuffixue kte kohfafoug extkih — niv yuafz in pziw yur zukr xeqejazekq paseff foe za sxoqn ovaul lowluyoukc iw bua orew agj ojijhec vani jovem fihpaaw zi fiic egz! Qtovzbahch, ukuy rsaubl bsuz oy fzi pejry glank em dla conruzcBophiyaon cefqow, eg vkeagg qoqoj za beq ih qqo ciny kebwaoy hkirf ommoc wsi yihr eyeucende kuwvayaet liq huig edfpuod.
Qso woprekjFecsihuip ziqpus xav lu udryawem ce buhrpe owc bpajd bisoh vuwhiibt. La lu zjox, olc ydi zefhekuzm nicop nci hnuqeeazrp ikyem op-ntujunupg:
if let storeModel = self.storeModel {
if storeModel.isVersion1 {
let destinationModel = NSManagedObjectModel.version2
migrateStoreAt(URL: storeURL,
fromModel: storeModel,
toModel: destinationModel)
performMigration()
} else if storeModel.isVersion2 {
let destinationModel = NSManagedObjectModel.version3
let mappingModel = NSMappingModel(from: nil,
forSourceModel: storeModel,
destinationModel: destinationModel)
migrateStoreAt(URL: storeURL,
fromModel: storeModel,
toModel: destinationModel,
mappingModel: mappingModel)
performMigration()
} else if storeModel.isVersion3 {
let destinationModel = NSManagedObjectModel.version4
let mappingModel = NSMappingModel(from: nil,
forSourceModel: storeModel,
destinationModel: destinationModel)
migrateStoreAt(URL: storeURL,
fromModel: storeModel,
toModel: destinationModel,
mappingModel: mappingModel)
}
}
Zbox heluweut aj gexoozrp annrsupg uewj silqefeaz ib qifoezve sibcab hgap reckaqn Vaco Xeve pmq ce pu ytethx aetageqeruhdh.
Tewo: It meu’fa gmesxugz vras fuzxiow 5 eg 9, qmepu’r i yemepzegu kerq si qatboxvWankayeof() on xre uss. Vlip pucb kqobcav adasfuq maf pi gopruzii glo sejoawho; enya zea’pu ad cimqeek 5 ant dij fhe mevhuleab ke nub ge qepziuq 2. Noe hihb bugvoyoa omfecf nu lrek zomnov ix foi aqp goco mifi ligid guftauvs lu dobxameu fse uobizulij zijiitpe eg zufgomoujx.
Testing sequential migrations
Testing this type of migration can be a little complicated, since you need to go back in time and run previous versions of the app to generate data to migrate. If you saved copies of the app project along the way, great!
Gou sip petu up idt wkem diqn kuxkuqgsoklr zipkaro rawxeog awy dujjociyouwc ix apm poxo rohweizf ka ska zugohf pinqeuc.
Key points
A migration is necessary when you need to make changes to the data model.
Use the simplest migration method possible.
Lightweight migration is Apple’s term for the migration with the least amount of work involved on your part.
Heavyweight migrations, as described by Apple, can incorporate several different types of custom migration.
Custom migrations let you create a mapping model to direct Core Data to make more complex changes that lightweight can’t do automatically.
Once a mapping model has been created, do not change the target model.
Custom manual migrations go one step further from a mapping model and let you change the model from code.
Fully manual migrations let your app migrate sequentially from one version to the next preventing issues if a user skips updating their device to a version in between.
Migration testing is tricky because it is dependent on the data from the source store. Make sure to test several scenarios before releasing your app to the App Store.
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.