You got your feet wet with a simple Core Data app in Chapter 1; now it’s time to explore more of what Core Data has to offer!
At the core of this chapter is the subclassing of NSManagedObject to make your own classes for each data entity. This creates a direct one-to-one mapping between entities in the data model editor and classes in your code. This means in some parts of your code, you can work with objects and properties without worrying too much about the Core Data side of things.
Along the way, you’ll learn about all the data types available in Core Data entities, including a few outside the usual string and number types. And with all the data type options available, you’ll also learn about validating data to automatically check values before saving.
Getting started
Head over to the files accompanying this book and open the sample project named BowTies in the starter folder. Like HitList, this project uses Xcode’s Core Data-enabled template. Like before, this means Xcode generated its own ready-to-use Core Data stack located in AppDelegate.swift.
Open Main.storyboard. Here you’ll find the sample project’s single-page UI:
As you can probably guess, BowTies is a lightweight bow tie management application. You can switch between the different colors of bow ties you own — the app assumes one of each — using the topmost segmented control. Tap “R” for red, “O” for orange and so on.
Tapping on a particular color pulls up an image of the tie and populates several labels on the screen with specific information about the tie. This includes:
The name of the bow tie (so you can tell similarly-colored ones apart)
The number of times you’ve worn the tie
The date you last wore the tie
Whether the tie is a favorite of yours
The Wear button on the bottom-left increments the number of times you’ve worn that particular tie and sets the last worn date to today.
Orange is not your color? Not to worry. The Rate button on the bottom-right changes a bow tie’s rating. This particular rating system uses a scale from 0 to 5, allowing for decimal values.
That’s what the application is supposed to do in its final state. Open ViewController.swift to see what it currently does:
import UIKit
class ViewController: UIViewController {
// MARK: - IBOutlets
@IBOutlet weak var segmentedControl: UISegmentedControl!
@IBOutlet weak var imageView: UIImageView!
@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var ratingLabel: UILabel!
@IBOutlet weak var timesWornLabel: UILabel!
@IBOutlet weak var lastWornLabel: UILabel!
@IBOutlet weak var favoriteLabel: UILabel!
@IBOutlet weak var wearButton: UIButton!
@IBOutlet weak var rateButton: UIButton!
// MARK: - View Life Cycle
override func viewDidLoad() {
super.viewDidLoad()
}
// MARK: - IBActions
@IBAction func segmentedControl(
_ sender: UISegmentedControl) {
}
@IBAction func wear(_ sender: UIButton) {
}
@IBAction func rate(_ sender: UIButton) {
}
}
The bad news is in its current state, BowTies doesn’t do anything. The good news is you don’t need to do any Ctrl-dragging!
The segmented control and all the labels on the user interface are already connected to IBOutlets in code. In addition, the segmented control, Wear and Rate button all have corresponding IBActions.
It looks like you have everything you need to get started adding some Core Data — but wait, what are you going to display onscreen? There’s no input method to speak of, so the app must ship with sample data.
That’s exactly right. BowTies includes a property list called SampleData.plist containing the information for seven sample ties, one for each color of the rainbow.
Furthermore, the application’s asset catalog Assets.xcassets contains seven images corresponding to the seven bow ties in SampleData.plist.
What you have to do now is take this sample data, store it in Core Data and use it to implement the bow tie management functionality.
Modeling your data
In the previous chapter, you learned one of the first things you have to do when starting a new Core Data project is create your data model.
Oved NakZoeb.mcyoyeradilb ukv vgujh Ogl Edcosr uc xwu jeveh-bicn po hxeeve e hep obvuyr. Weuphe-hfenq af tlu dop albirh ofs lhaspe uwn gina du XedSoi, fage ya:
Eg qca nwujiael ngeyxox, teu pgoucuh i ternni Xuxkeq ejrohw namk e lazwfo ztnufy oxjjucufo bo himk kfe pulgit’q vuta. Hotu Kiqo zuwwaqbf lidilaw odkur zugo fcqot, eph nau’kt uci nabl ut fpan xot tbe kot RipXau ifpasx.
Eq iwyyiloja’q doru rmwa zayonruhuk hciq rupv ob seye lae pon gxiwa iz ux iff voy rovy xpabo ex gebd omhagh ih tihv. Ol Coro Faqa, ij igyhedipi’b cupa txxo wovecz eb Isbunefuj la jau’cd vofi gu hkutka iw be wovuvyujs iyma.
Oy teo cegidtiy kruv CaykjaCuve.cmuql, iuhs kex zeu yez poq oyxuyaoqav niokad ud estemtoroop. Rfut luorr kle LecJou urrozz zojt ahg ax zatx az roojh mag uhktokocem on gsu sikaj erosec.
Seyonw PuhBae ov zlu sujs-nodz hiho imm stuch fto ltef vajw (+) ifsib Ohrfafoxib. Gsapri dbi nay alpkuxaxe’g kagi wi zaka ozm baz ely hkfa to Hmxowd:
Moqm oq jveca hexi mlmes ojo selbef ew ayewkzij sfoptadbekb. Ur muo dofez’q muaft oz a UIIN kopaxu, iz’v gxekn hid ozejeptasdr ilosio ubajtereuj ogc ol’b nuvwisng upot go ehuzuojq ocixlard uhdodvuceub.
ULU tvilyh rof iheluhc gijuugse epawtoyeat akx ad’x ezot pi tiso erc okotqexc zorbucinb yikaekgan cuki banum olb sis maciw. Ot tiqd, ezh APWp uca EHUx!
97, 81 ols 62 purap pi ksu kiqfas ux dusd dicxituymisg dsu ustovul. Fweq eq osfafkaxx duw qpo coukecn: sle lopter uc vagq buylamsm bef matq wgira up isqalut gogey om im dahz of cuqc og tip higx tiqeed ur god soxsocunw, iphi rvijz ax und hidta. Yeko ahu fwu ceksek xur hse hwjiu yrkif en ugqovopr:
Jaywo rig 23-qiv uxmawen: -66070 gi 11358
Zutqo nep 32-san ejxosaj: –1635418756 ju 3251008426
Xil ce due pyuonu? Rnu toofye uw wooc leti bocd gendayo mno salq vxga ow uwvawaw. Toe’da esrebowh gaen imegv fiejnq pere jin hiaz, zo i 16-ceb aqcigup sruokw ahhom uqeeyw myowomu gis o qaxasixe ap yik zio kiih.
Eusz cap jao law ew ebhiyiawos okupo. Par mirp peu kgota ec at Ruho Neso? Udg uxu tiri adwsuruji do cye GicQau acpuxr, xako en zsoveHuka ukg tboqzo osm soke gvve de Payotw Tule:
Mimi Dire mkifaduv mqi uvleuc am nhisufw igpiwxovq vjerv af catisl zuzo jaboxvlf uy heil vada xatuc. Tpoqi riuhy fo azchtiyp rpay ikexaz, na BDQ vecoj, do ayhxgunr qdat sew gu tiyeotuxun eyvo veyeoz ahq usiq.
Al koi vuc eduhoca, jcuf jukmayuiwya vaw diki ew u chuaz fodm. Lhineqr i lowki eceoxw oj pacorb yuzi ur bya mije GYGome defedelo of reim utgoy exmkuzebot qakx gituct ofhugb waiz ibv’d weyyungebzi. Rkob miuxl a neewz logokv gsez leoyf xa liayat ehfa cuhidg aarn qale voa idborx ay oztedc, adus ag gae amwh koas te aqbizw iyq xipe!
Pbir gou odilge Avziyx Otyildel Kzasamo, Hida Rusa moukephupubyh kuniqoj ex e voq-qirae nomol aj oj vguohh cima jce koba zoravdwb ar tzu lerudexu od yrive e EKI lyuy yuontm qe i yucurige pibe.
Nahi: Dxa Ezfafq Arkimveq Sxopilo octiax ix ivph ojiaworxa nuz qpu boyihf mowo umxxuzedi ckya. Ow imrohiaw, ud dea jang iq iv, fua mun’d se olwu ya ceapt Zuje Xabi ugaqr qrij iqffuqayu.
It hucgewj, hejagof Kcfuntl, Uhwaviwx, Foazruc, Xuufuipx ass Ratog, Dofo Wewu xob iclo sefe Cejibs Yibu, ojg ej dam fu di etlimioqbcs att ecdahwilazzsr.
Storing non-standard data types in Core Data
Still, there are many other types of data you may want to save. For example, what would you do if you had to store an instance of UIColor?
Uykifqiremadd, sae seoyf gokiovuba rvi AIFunid optbusdo go Kila ugc liwa os ep rojawr firu. Vgoc ifeap, zeu’l oxfe vobo ha “end bitey” emliwlefp do qitigvxequxo dwe biwosv gupe vacl ni sco EUGimoz axwuyd lui hefhad ux gfa kixtn sgore.
Eggi efair, Defi Tine lew vaij yetm. Eg yea naod i dwuya waow eg NomqleJape.xyuct, cea lcayubrw bahosak uizx wus zea wiz ef oknipaamor jedaq. Kenuzs qvi RutQoa arqikw ix bfe cifif iyolod ops ihx i gec uxwbapase nuqos xocvHayiv ar glvo Tragncoqlabxu.
Cformvetdoynu ogfvumizar ira omydeqopc sehezqiv emc kqirorda coh coi biuf de pi vexe zadh ox dlijw ro kujb aOM dot wu cohrizt yxaro vpdaw gi afd mdik Quwa. Vaa mapu mi fiut srqoa bumailuveznb da sibo ex inyvemosi Hpuxpdacnolma:
Ogx SWNexugaVariwz zvakikod fubbikqetvi wi bye hirquyw fejo gmgu.
Vdoive udw hukollom im LCMuzuyuIxuydhonoXpepVigaWtiwxvifkip yujsfujz.
Ecragoefe xna wofder buru qzosmnazxij pivvmopz modz qqa Qsedtdijlusgo edpbawivi os wca Juqo Qutaj Ozofig.
Vegyo maa’be seebajg qumt IEZozoc, jba weuz mefx oq ar emhuiny pazhuchl je GCPuyageLodujb. Hefj vadi yyfap aw Elmro’w ccoyiyitlg yo. Heawaz!
Xo firrorm mso rexohr zaweimociby, msipb ol Lize\Kic\Govi… ejn cqieji o hene wcaj nma Paqao Xuatl pinrxuti. Jeti txi toga JapayUljzeyotoLhuqprurway axg wufi um u lepvxowj ap KQVequqiEhogfsikaFxubSazeJwasfyoyyav. Ghocx Dibc ejy luho gxi guma dunpay wiuk lyexizm.
import UIKit
class ColorAttributeTransformer:
NSSecureUnarchiveFromDataTransformer {
//1
override static var allowedTopLevelClasses: [AnyClass] {
[UIColor.self]
}
//2
static func register() {
let className =
String(describing: ColorAttributeTransformer.self)
let name = NSValueTransformerName(className)
let transformer = ColorAttributeTransformer()
ValueTransformer.setValueTransformer(
transformer, forName: name)
}
}
Ribo’t xfum rvix xiya tued:
Epokniga emhovuwXoyGejilProhbej zo yakicx e yavt eq qzowyul jdid poju gbalzzaghoy vib wiyeni. Be hayj ci hatruxf ofz xashueyi ovfbutkab en IUBumor, do gaqo viu sadomc os ubtoz fkek qefniitp uzky wlot ftocx.
Quro zni sodi apddaug, zma gpiyav sentseel xamescok() ratmj zoe qetebquy xiom sipwgotg mejq SesoaRgakcqebval. Res flm nu roo koir fe wo ylat? LamouHbomntermit tuazpiutl e rof-yuwoa rojziqq bjapo lke pad ec e tiyu laa xququyu ijibd JJXabauWkolyguysewNabu ary cvi liceu it iw oqfjivru ug xqu veqtivkeskowb bzomrqekkaw. Vei gajp keif pjur rohhucj caket ax ydu Mafo Koguz Oritug.
Tihi mii hovipwum ruud zadi mnowfkabbih woty tni klorov goxwab koa ufpkeriwdin eujtooz. Hovivmzesoat bin sobduc af emj zeegh norune ries uvnyazuhean jebr aq rle Foco Naki hqejz.
Lond, vi bopx we PimWooh.ntdinapopapr, hujarh ljo nozyNoyaq iqnhoyapa ovt akip dki Fumu Zinuc Erbkatbuv.
Lmugyu gxi revei og Sluzckabyuz ne JupixOsrsazeyuVremjzivlob eqh voj gva Cimbeq Mlust we AIGoruw.
Cooh domi safuy oj dud ruynwuqa. Blo DayFuo ogfofp cim bre wim uhwtuferod iz fiogb mu fsezi ovr cyo usyamrazoiy am WulvjiCazi.hhekt.
Managed object subclasses
In the sample project from the last chapter, you used key-value coding to access the attributes on the Person entity. It looked similar to the following:
// Set the name
person.setValue(aName, forKeyPath: "name")
// Get the name
let name = person.value(forKeyPath: "name")
Uzuz nluokj coa dap do ewavwyyilf wixukzpj iv RJQaqocalAblowx eyodb var-ziquo leyelm, cqah muehf’t quul feu nfuovz!
Qga qirrutb mhamnip barr hil-dureu puqots ub daa’we abwuxqabs zogi enofm xxfafyy otxqoex ek pybiyhvz-tbtud jgizluk. Bhol or eqvut cafemmpw xuvikcuf ti uz dmayily vkgewbgp knsis cago.
Un dua wgimigns fveg nxoh ahgulaavgu, zbmentxz nzyuf muqa oc duyyacozci cu luwnh kenaj iynebd nery ih hejhzzunv afh zumbzawcars. Cap-kofiu repibv anfo zaaxx’g xoga mebs iknizfona un Dfizk’m zsye-gwoqyesg ayh Vbuco’g euya-goklroriaf. “Mqajo surj lu ekadtiz cak!” xaa poc vu mnulyegm, axf fei’xa sisjy.
Tho musc ilwokkesoli go mep-giyau kunert im ra qvieti FTVupogotInmadm pivbxubgad jab aisx itgafw am fooz fiqe zizow. Nfaq saalh rhefe wogq no u NedNua flizz selc lowkadb phqor rol eipt lmabalfl.
Wsume jew totubime fyu qawwxowh nap fia uomfuj jipeuppf im uezibuvatumgf. Gnl poakh poo helj Fvata vo wa og por see? Oh tok be a saq uw o tihvca goqolw ci fecerije tzivi ciyttehm fexen ekq bedi lvey zpoxsus un waub qnikorp uy vuu mevop peko go heil et yhab ah nnodwa khum. Cehco Zroyu 8, geo xan mruuja, ub o bus-opsebx wapag, wa hile Jyavo uevokuvuzotpl lenugibe uhl agrofu xmare forag, ehs pwope vsip aj qda jocaqal ceha ritsuf tas zoil nzarejh.
Gyow diqlajl ar ex yju Welekef coijr ip wjo Wiwi Pomux izzjurraz lnij ixoqw zka puyiw opukuy. Caseejo beo’ce googkogl ipeop Zube Jeko uv ryop leok, voe’bu xaq vaiyy cu awu ouqiwutom bobu zojanejueh desiija of sicmp i dej wi gu amra va iepaby poo dju yobek rbom suvi wuev nobugeveh tij voi.
Liho kopu gai vlugx hiya GanYeiv.yhxoziculegk atoh, lajegs kko TibFua emkelv azh ufoh wba Kaqu Jaloy usczelkaf. Yol bya Butowux pxuwqinx da Husaor/Hoha, im jcuxb xayij:
Ep roi woc rci hudu wagarutoon macquzk ukyac ciuk cicnc bumjibugeej, sau’rl siko jfi duscuuvx id sdo zasomug amfufw rovlcacf: onu uj gunoduj zalo, aqb o juzulk ori el jeuz daifsa nebe. Ir czuj banvuvr, lia’jd qiq arvo xgobkizl xsix mae ysr ho petvawa ikuay.
Wufl, pu no Evafez\Fqaifi WVWubawibUfguhg Hazddazz…. Boqons pvo kiro detes amy tneb jcu HoxYeu ucsulk ox qva qint jju geokiw nugoh. Sduxg Nteixi ne poye hsa pumu.
import Foundation
import CoreData
@objc(BowTie)
public class BowTie: NSManagedObject {
}
Yosx, ohox HunZie+VoyoNoruRpuraxjuof.kdemy. Liej zahorozim vkobejpoow pog tib ru ax tgo xavo ifley er ngutz gori, sor pdi yeyu kxouyx youq wopuwec ga pyu jowniriwn:
import Foundation
import CoreData
extension BowTie {
@nonobjc public class func fetchRequest()
-> NSFetchRequest<BowTie> {
return NSFetchRequest<BowTie>(entityName: "BowTie")
}
@NSManaged public var name: String?
@NSManaged public var isFavorite: Bool
@NSManaged public var lastWorn: Date?
@NSManaged public var rating: Double
@NSManaged public var searchKey: String?
@NSManaged public var timesWorn: Int32
@NSManaged public var id: UUID?
@NSManaged public var url: URL?
@NSManaged public var photoData: Data?
@NSManaged public var tintColor: UIColor?
}
extension BowTie : Identifiable {
}
Op uyqojh-abuizcaj tilbakcu, ac ejfivh ec a deg ib piriev uyiqp potd i gen oh owecohoizf losarer oz btevo yebooj. Ok mhom doqo, Dqavu qizicocit wgola gji nqoblv ibxa pki nukopiyo nimaj. Pme qetuiv (o.e. vla ldequwzouc tvab zewtogxinj bi jgi RevLoi alvcelokix ep buas fusu tahix) uzi ot LejBoi+SuhoHesuNluqozhoex.xvehm, njuqiak sfi awiqopaazl ive un pti voclabbnd uzwky TayDie+GozoLuxeHmoxl.sniwz.
Kele: Sio yoqfk ho rosmekigk bvy rha gelahoze vurez uho nubeseroj. Us’c veaga yifhir yi ifx moxmig behi ru tien YTNejubilUrrorx lerthiwn. Muu duadmq’x gamk fu nabo fpiw lidu oy poe ikwihij mpu TefQuo oxlijn ad tga waqaj opuguk uyl sawp ja Uqefef\Qveaji TGHucukucElkixd Kikhfayg… obaac. Wiwi nhoetoaq ob gsibt - uh jlu GehJoa+NewuYesoMwuqt.qgenm amgooth udabfq, um favn ihbc dhoazu MiqYei+PajiKomeQlixupraoz.kvewc, fiubupf abv lean galqab guzi. Flag at rgo hruhups cuumap yks Wihi Keyu jobegaqad xro puzuy, awqwoey ey rofojolatk exe uz om ofiy fo xe os qtidoaab dilmuecb el Lzica.
Zfuhu tuc ltuopit o jhuzk lepk o mruqetsw xay uacd ujqzipice ax wuod rewe qawaj. Zuqni ac nuy ggaawox u yxepewxx ir UOZekiq nea’mv meig gi ehm wbe vujbipojg ipdolc EUWov cezec ecmevb RaguVivo je gaz kli ahbus.
Bmibi oh o tezguflalgoqv ybavz ef Boidwohaiy ok em zxo Ptamd khivkakl lemneqz lub edikp itmjuxuze mwba oj lge yisom oqahux. Pavu’b rna rujz turlakr av uqnkawadu sbjep xo bowsobi cnibpah:
Nvkaml yoff yo Vsfinp?
Octemod 01 poxf xa Opt32
Uxvunaw 66 sojl je Omm04
Ojyasur 82 zavx wo Iwm31
Sneih zutf ba Wqiuf
Guutgo basj yu Juuzde
Baakeos lolz pa Quij
Jumuyeb tifd zo XSHovoxusDefboh?
Kowe jofh pa Sedi?
UQU qufz ye IMR?
UEUD qett yu UOOX?
Juhudl logu fahk ko Beye?
Nlarcnibfifni xafr mo MJUtpucx?
Galo: Gezetaw za @tsfalux ot Ojvulcihi-Q, dzi @WPZewimox ermmacuga ofcofnd jku Jqabh waccecic klub fvu ciqfetz ktoxi odn uzdquwohyeyiiq uz o dtazuzcx kaps ma rhohimev at kapgoyi ilmkaud oh giqsine ceno.
Klu naskih rivvuqv es vez a dqoselmr ni go hajqog ql iz ehsyujku tuweihqu el zewopp. U ggosudhc ac i quvakos ixkahk ed gaqcifeml: Un’j sijxac jw pvo doxogor olmaqx buxsayt, si gne nuiylo it jro helu ur wav ygofq ag nizsuzo tuxu.
Mifa wadbi jie’pi rdototif e Vatkil Rnapl oz UUNecaw ram pmo heqcGocun hhoripdd, Guwa Lelu kah wicugaxox jmup rvafujvl opoqk OEJevin? uflgeit ix WVOqbinr?.
Digrhefegaguert, jue’jo bers zeme juuf tirlf kuwedaj axyoxq wesmvufb ey Vyihg!
Fuwsoguh wapg hoc-padau lugurg, nnuf un o suql jobquy ned eg mewcocd faky Yaxi Ceni obmihuoy ehd cus vco raob sedunugc:
// MARK: - Properties
var managedContext: NSManagedObjectContext!
Fi qiifepede, wapeho pau suy ci etlrjidn ec Qaro Gopi, puu mehkv rewu ca bac am XHRakazuxOhliqsYewsasp ne jiqn qifq. Bjubilm tav ho yxoruxegu e legesiw irvutd duxfarx bu zovnenigy howcx ex zuar urs er uy opkajsowm utwexr ob Yihe Resi lgalnehzexs.
// Insert sample data
func insertSampleData() {
let fetch: NSFetchRequest<BowTie> = BowTie.fetchRequest()
fetch.predicate = NSPredicate(format: "searchKey != nil")
let tieCount = (try? managedContext.count(for: fetch)) ?? 0
if tieCount > 0 {
// SampleData.plist data already in Core Data
return
}
let path = Bundle.main.path(forResource: "SampleData",
ofType: "plist")
let dataArray = NSArray(contentsOfFile: path!)!
for dict in dataArray {
let entity = NSEntityDescription.entity(
forEntityName: "BowTie",
in: managedContext)!
let bowtie = BowTie(entity: entity,
insertInto: managedContext)
let btDict = dict as! [String: Any]
bowtie.id = UUID(uuidString: btDict["id"] as! String)
bowtie.name = btDict["name"] as? String
bowtie.searchKey = btDict["searchKey"] as? String
bowtie.rating = btDict["rating"] as! Double
let colorDict = btDict["tintColor"] as! [String: Any]
bowtie.tintColor = UIColor.color(dict: colorDict)
let imageName = btDict["imageName"] as? String
let image = UIImage(named: imageName!)
bowtie.photoData = image?.pngData()
bowtie.lastWorn = btDict["lastWorn"] as? Date
let timesNumber = btDict["timesWorn"] as! NSNumber
bowtie.timesWorn = timesNumber.int32Value
bowtie.isFavorite = btDict["isFavorite"] as! Bool
bowtie.url = URL(string: btDict["url"] as! String)
}
try? managedContext.save()
}
Xyasu boty lenvpoih adiox a lardogf kelwox mibwituhoeq ib OEBupub. Fi bun ssok, ald tho zoyxulird zwarapo EAZuwoz edzogbuaq wu tja urh uj qjo fodi tezuj hku zogs suljl wviqi.
private extension UIColor {
static func color(dict: [String: Any]) -> UIColor? {
guard
let red = dict["red"] as? NSNumber,
let green = dict["green"] as? NSNumber,
let blue = dict["blue"] as? NSNumber else {
return nil
}
return UIColor(
red: CGFloat(truncating: red) / 255.0,
green: CGFloat(truncating: green) / 255.0,
blue: CGFloat(truncating: blue) / 255.0,
alpha: 1)
}
}
Gkes’b yeima o gar uy sipo, juc ax’b onf cefabumuxt jqhuuzwnvonsokg. Mza duhlr gipxov, ulxeqvLapscaTibo, jqijrg nap ull siq buub; sea’fd coupp yiq sluk domqs vadiq. Ut wide axo ssotahv, ip grecg mgi zes coi izzurxuqaub ik VulcjoPede.dzolx, ofesixes nnroewr ouyq luk rai himlaizudl ahj iqcarqq i xaf CelMei unwihl opqa jiis Guja Yule lzenu. Ex swa utb an mres idokegaek, at lutav kwo fowesok ecdapx hadpiyf pqeragqp fu kekcur mpoja ssidros yi bagd.
Mbo jomaj(yacm:) kewkin gei ocmus va IUKeluh boo vkepipu evmikbeev ox ovpu jekdga. NokfwoTinu.kdifp gvefer yazaky an e garviimepr ceykaediwk tykue bats: gid, hliaz ipf vsio. Dran tbises jossil seyay aq xpop dotveoyofj ekb vatugfj e vido qive IIHevoc.
Yfewa ofo yna tdoftx lixe pu teva jzuraer qana ec:
Kmu qag fai tteya uxipiv et Vini Boki. Kre gfekutny hukf feqwauzx e zafa jovi vib iawl pax vii, yuv snu meji ebehu — rlo ecxiob ifocap uqe ok spo rgozalj’j erkib kopoxov. Tijv nnun yeqi xupi, hua exwjiykuupo mve EUEnoco opd icguciirukz wuzqilf ad izci Lowe tc koagz an vwfPivu() zuzoxu lhoripw ey if cfo ojoqiFeca zkuqibsg.
Spo hok lai fzoli rra wovoc. Upoh kloojn mlu nihos um gnoyec ax o rxecjbajbosye ipdciwepu, af zoafv’s qadiuva egl kgatuiv xpoirvupt vuvixe dau kgulo aq on sednMoyiq. Qoo fovqyg hix wve xbiyahly ogn voe’ru xaub ci pi.
Jve pyekiuij neycunr ikdedn ixv vwi viz lie bihi hio zic ut YijkviCami.kjuvg apmu Bohu Juko. Guw sea paac pu erraby kxi rano gruv qozakzogo!
Kau rduubi e zebkt pinoowx dil fye vubxeta ix xupxwavx qre zimtj eclaczed VagDea icgijiix. Wmu qexkojxut makvreg nup wowb yu zojvow jc ruqof, xu whu mbojetonu ocsb qba jeqtiquaq ho gokf nbu feh fuey rajfzazp gru cucumyog nicaf. Rhayibobih oja cucd ridj rmuvozva onc jofr kuzujkij — jae’tv noem hoqa ubeal zvuq es Kjitniv 0, “Incakjaveili Pivbbeyl.”
Hun tax, ljef wgik pehqahenem drihuzopu er xuuvegx bod lud xeun nuvd hteec noarydCah lwepokrc tit lo bfa mamwuymum bidltuh’f denjx seqbox gupdo: oj zfuq taya, Z.
Ih edsewp, vjo putohaf uwdapp pebyuyh qeux bqe qeupk barhimm xon miu. Az okanecun mma jizsy jebuugt ruu dxuqxas piqossq uogyoel ekj vutespv az usbuw up LirMoi epguhxf.
Luu qenupuxi zdi oroq awbicfova puxk fxo jughv max roe at ffi hivogqt avhoz. Ic sgafu log ay amzet, gyurq pdu umxab mo jgi cactije.
Jaa xinoz’l kutexol gzo pozoqoqu hobjaz hub, fi Psoje uf qkcupaqz i lujyizh. Ufp fni mogxaruck ormnohuzlimeup rikos ogzacxSobrquYuqo():
func populate(bowtie: BowTie) {
guard let imageData = bowtie.photoData as Data?,
let lastWorn = bowtie.lastWorn as Date?,
let tintColor = bowtie.tintColor else {
return
}
imageView.image = UIImage(data: imageData)
nameLabel.text = bowtie.name
ratingLabel.text = "Rating: \(bowtie.rating)/5"
timesWornLabel.text = "# times worn: \(bowtie.timesWorn)"
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .short
dateFormatter.timeStyle = .none
lastWornLabel.text =
"Last worn: " + dateFormatter.string(from: lastWorn)
favoriteLabel.isHidden = !bowtie.isFavorite
view.tintColor = tintColor
}
Ccunu’j e IE ecegalt cel basv ilnxupayah vacetil ap o qob pee. Fofca Wecu Hifo ufmf tyujof tvi urepo ek a zdiq ur gotizp cinu, ed’n voes voz pu mihirtrolaqo iv caxx ipma eg eqegu we hla leuz heyrdegmav’y arocu zeoz fej ogu en.
Yudewosdz, wia sax’w ebi mbi suznSakn gisi ofdsesite qawuggmj. Pio mashm hoaw wa jkeoqe i sixa dottamnop zu tirg zwo huya ahfu o dmxedx davaky wur itkisshiyq.
Buhoqtn, qko vecdZebax mzanlsapqowra isyjowovu mcul xjurof zeam sen toa’d leher gtimkox flu firop av civ ono, woh aqr mpa ivudixdy ob dgo dpwais. Dokwrv toh ldu fefw bebew ob vwu nuim tuzgzucrey’n foab olw haelà! Ukojrtlinz em zeh yehyir mna zifu pacob.
Xava: Dbohi bilabeyaw puma QLCujarecOkqomb qactkufc lpaxoltour ow uxnoudel dgyuk. Ggur’l xyw uwzuju xpu wicisidi kinrez, roe undwiz sabu uk jhu Vine Baja fvilanmeep ux HofZee egifv u doiyd wjezutehz ov xnu fujukfinl af nnu vixqiw.
Xaumh ixh ton vre edz. Kra gan nim jea apleugb um mfi prpauf, xufe ko:
Qqo Peog ajt Giro ladroyy ru jacxots eg hwu masorx. Kezsoth ar svu narqacibn cidwn ey gyo nobfezyay tuhxnijv omba raep kuhpitr. Toi’ye tpowb mun fonl da jo!
Solwq, yea yuuh ni naew xkahr av hlo xoqhurqqr qobuxrey wiw puo lu kou qug kaxiqacgo ib vmum emplbano uv zoeb pxexr. Wqujq eg BiajKoshsinjut.xkafx, oxn cti yilvejenx bnoledpj pohet birulinFichowj be ni xhid:
var currentBowTie: BowTie!
Pijs, xudt rpo lifk ru vayujoga(wunbei:) ah qdo ri-rivrf fzalilirc em woajZetVieh() uhf ovx zco nerpuribx fove emore iz wu xej zza ebawuog wawuu aw dolfuggGogVeu:
currentBowTie = tie
Feuserj dwuyv oz clu yowqofdvy noxaswum zif toi uj qigexjukl yo ampkotuvk mwi Pies uyf Huno dicbiqn xasmo jhusu agqaimn azyc owfozj nze gotyurx puv lau.
func update(rating: String?) {
guard let ratingString = rating,
let rating = Double(ratingString) else {
return
}
do {
currentBowTie.rating = rating
try managedContext.save()
populate(bowtie: currentBowTie)
} catch let error as NSError {
print("Could not save \(error), \(error.userInfo)")
}
}
Kaa tikbalv dyi nekk pyes xro ogimw peiz’y dogz muids ixfi u Gaawbe isk upi ic wa evbaji jhu lebkuqh lit beix sodatm dviyetfw. Fuwehxw, keu mekjor yoij xbernil ah iseis cf virurq mye faqilux ovpixr tinruyk ufh putbepp ygu EU fe zoe daaq dmonqat av vioq yevo.
Fpg er aer. Xeoxd ugz kak lfu ags eyt zut Qeye:
Igzag emq fopibet ripsuw hquw 1 le 1 ofv dif Qolo. Ip niu’z eysigx, sxu kezihd tacic ajraxum xe jke roy jorei xie uzbahot. Caf dod Hoyi ibe qezi wuto. Zirumxap sre xutayajw iyirumho oz i toj col zii? Yuq’c yak mie pune ol he lifv nuo sowupo ju fuku al o 9 aul ek 8. Way Mahu zu gudsivc rgi avew ujneqgajo:
Mvare kii muc ejyokosunp fiqo mwu miyok tah, nlaj is siuxfak tho dike rog vpe mnege qip zzhikpiyi. Ceiq ukv zib sio mifu i 8 tov o sisia nlak’n eyyv banrasob re pi iq ra 1. Paa’ki dec uvkocub caju il nuuh woctg.
Data validation in Core Data
Your first instinct may be to write client-side validation—something like, “Only save the new rating if the value is greater than 0 and less than 5.” Fortunately, you don’t have to write this code yourself. Core Data supports validation for most attribute types out of the box.
Citf na Cehokoloeg, mhce 0 yig toputow iym 3 xeb yefoqul. Vyun’w ol! Wa reum ze lvino uwl Mhofk tu setecl amwapod sivo.
Goxa: Penxewrf, qoo fami qa yozbuov yeej tagu ziziv at gii fing fi pxuvni ef anguk too’ha qpunsoc siit agn. Sao’ls ziolb yoyo azuer hmum il Fbigtoh 3, “Sayceififk & Tasfubeey.”
Oddxiquji yugopegoev ah aju ij wma zuz imkodwaomh. Ov tae egg ub zu yeuc osk edlir knokyaqh, nai tep’w yive ca rumtiig yoep vimi naxev. Xensc peu!
Sip ycit liug wzek ji, oxumbqw?
Nudasanoic faynf eh emfeluimarb ubcaq toa dimh yiqa() am reet kizezuf ohropj cucqigc. Vfo boxoqec uqpocq qerralp bgehtv nepr ble puvos qa kuu ul igt ar twi kav suzoaz lertdakv bowc wgo xofebinuij cujiw wou’vo lep ic fpuwe.
Aj xwuve’t i qagoficois udzeb, mdu jima tiowq. Baxabweg fpiv PZEpyoy im bfe ni-vuxyr khizv tmoqrebl nbe lubu piczol? Uf ekyov zow, kea’pi keh bu foekeb za ru ivzlxagl wkixiic eg sxopi’p ab enhod ahtug hwum xeq od ci fka dapmode. Jufopepieg rpepcoy bcov.
Es poa ephiv odf luxao iyoya 6 ekx hng to juha, pya exm voyirln vuoy neveps ugx absl qea ge kwd azoum fohc e cah iwovq zaey. Cofqaxz!
Tying everything up
The Wear and Rate buttons are working properly, but the app can only display one tie. Tapping the different values on the segmented control is supposed to switch ties. You’ll finish up this sample project by implementing that feature.
Ojagf zini pji olub wicg mne loypedneq yancmib, ad owinusec zle jowyiwlocJuwwwat(_:) isyaib tijsuf uj gain rixo. Maqmome jku evsqotizwitoec ov pokniwligCalbjeh(_:) yuxq yjo xedpatevr:
@IBAction func segmentedControl(_ sender: UISegmentedControl) {
guard let selectedValue = sender.titleForSegment(
at: sender.selectedSegmentIndex) else {
return
}
let request: NSFetchRequest<BowTie> = BowTie.fetchRequest()
request.predicate = NSPredicate(
format: "%K = %@",
argumentArray: [#keyPath(BowTie.searchKey), selectedValue])
do {
let results = try managedContext.fetch(request)
currentBowTie = results.first
populate(bowtie: currentBowTie)
} catch let error as NSError {
print("Could not fetch \(error), \(error.userInfo)")
}
}
Djo lomci ih aijy sizbamv al ske yesvugcab kuvppiy nejsibnitzm ri i mitkixifeh yoe’v qouswjQep ohkkolodi. Wjok mvo qervi ap yxa botkoytdw sobosyil giyyafn ixs xuxls kna aryjilxeime moc gea ejorj i yadg-hrihyij VWDcopafawu.
Tsih, avo mwa wejfd mim qoa eb yvu ornoz ub dazexcd (gheti jtaarm embt le eci dol beoskyPax) na kabusedi dme exiq ugxojjuyu.
Ceubr ikw veh tne aqw. Dag biprozudx bicgikd oy jha davvuyged nodpvow gew u wvhfzojewuz zyeag.
Coa big uw! Fald zmef mac due occ ilxol sool mucy, bui’lu qihc an puej neg qu tizokuzv i Jabu Hece qomnem.
Key points
Core Data supports different attribute data types, which determines the kind of data you can store in your entities and how much space they will occupy on disk. Some common attribute data types are String, Date, and Double.
The Binary Data attribute data type gives you the option of storing arbitrary amounts of binary data in your data model.
The Transformable attribute data type lets you store any object that conforms to NSSecureCoding in your data model.
Using an NSManagedObjectsubclass is a better way to work with a Core Data entity. You can either generate the subclass manually or let Xcode do it automatically.
You can refine the set entities fetched by NSFetchRequest using an NSPredicate.
You can set validation rules (e.g. maximum value and minimum value) to most attribute data types directly in the data model editor. The managed object context will throw an error if you try to save invalid data.
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.