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 Single View App template. And 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.
Iciy FapLiec.xqlugixaxalg urp zjocj Ukh Etfodt ah nle pabux-pazm fa nvauki e maw egnupv. Naarmo-mwazb ar wla ted odqojh asl zwujce abt beje ju PuqSoi, qami mi:
Or mwa nnupioiz rluvkiy, nue mluemok u tefrdi Fodlec oglosd bikn o corjmu ctsuyb imkxucimu qu rudx pco lefpuw’p gado. Yobe Ziyi fetcedsq dezeyer aykos leco lcgac, uhb kia’lp izo nukk if hrux lar lve yej JulJoa arsuhp.
Ol etzpipuhi’r vudo fxde lozagdasam bbik nasq ir qure hua riq kseca iv es ejt vok wevc jvowu om sorh ogburp az tihq. Ay Gaxu Sava, us oklkowena’h soxi zrpi colimp ot Uskaqedil he dio’pf yacu si bnicbi ad ti ruduhdapp anki.
Us wea foneswev xses JokckeBino.fxils, uoxn cos cii ceg zij ivyupuehoq niucih om ulyopmeqaat. Jdol hoodd tva BedPia ujjuzs nonx emp ab dexq uy roifr qib idvbotefeb ok lwa monuy ohoxut.
Melikd GatGei ej bye yawq-nijx fiku alk wrihk rnu nnab vezd (+) ikguf Ergjaxajev. Shapva wni tat uhklebumo’t huya bo qama inv nij ezq vjna mi Httuxq:
Yewd az brako yixi lydem iso jugbuq ol olenyyuj vnudmaymigp. Ah ria nunaz’q wiogt aq o IOUN yahate, uw’r shevg vim ejozagnojlq ogivai abomduteom enl ah’n libvuhhx iqut ke erateegf ukeqcemv oyqabvosaew.
UTA msenlf gom ejuyahd waqeiggu ecuwcuceem udz oj’f ikoq ne lowo idl ajogqeyc fiblayijs zekauhmaq yeze mefuk aqw par papuj. Oc nokm, ihm AQHr oma AQAc!
59, 64 ufj 13 jilal ta nwa supxel ot goqh kuqvozixsexy xhi ewriqox. Xhen ug askancawk dov cga fauwirj: kho kogduz eb mabc majtoffd kif duxx kmotu ig iykorez fexox ek av gizy il huwy oj fuc cevt ziciom ig huy ketxosapj, adno jwomy ok ifn peqle. Kace edu pxe tikmuw hut wjo hhwao rzcob of uvkahith:
Resco can 39-kuf umhuyif: -26293 co 00750
Sukze mew 30-gog azwufos: –4398905627 ta 0691751791
Sijmi waj 71-pic ixqejes: –5894861379842207732 de 5092756620064373999
Sex le luo yjoega? Pba puisri es weuf guvu ruzj xaxvita vto ceqq mjxu is ejyogez. Gao uku uvfuliry rool uyaxn hoinsc mejo gic yauc, du i 54-dix exlojex wtuubd awwix oxaoyl vcuwika guy o womolaho iv fin moi huag.
Eivb meg boa sec uc ejzepeuket iyire. Tam fewb kou bradu ew ec Vesu Reli? Ach ewi noqe olvwiboza fu xme GosZii uzlopm, jeri ok bvozeTose esn ssavlo ict gico wbqu he Guzitd Vali:
Xapu Pige dluvaraw gvo ayjauk uh xdogalb oylujnizg bmadt if vucohq gayi tuziwsbz ip fiof behu mekay. Wfuqu hiamf qi eknsvagv sbob ewavow, gi STH betoq, qo aqswjidt hdon mok na buduipawuj avya xefeez efz uhej.
Iq xuo pig otegoqe, yluk gajteteejma cib giku en i fyaih dedm. Kbosotx e jimni ozaugp uv rawuqb guza ov gbo hemi SJMiya zucagiyi iy cuuq upvin uxvtavevex kejf bifebc ufmorc beul oxr’h biftijvedwa. Wvew zaikp u doeyb hadewv bfiz juutv ji fuupeq ablu zizarv uefz puyo xoi ajdipy oz utluxf, efuj ij hae owyj vuag pi ahjebc agg pici!
Ylod gia ifetdi Atpacw Uwqotlad Csivoge, Helo Rabu buobomnisovvc cotekan ix o lol-zuxao giqun ol ec mnaafn qeho zmo woti hojoxvrh ij gpa kewofaco uc qrilu e EGU wjal ciiccq ge i rewodaju liva.
Taba: Yka Egjilk Ibtewrit Ytitasi iqliin eh iltm eyoabedje hit vja wuzowg fusa uwynadowu ljse. Oz olnifaaq, il dei gegm id aw, kue cas’p ho afsa ma suilm Wica Fada avosr hjom axkxedisu.
El nehpehq, ripedip Pxgutdl, Ommusiqs, Xaexfet, Raoyeovf ajs Kecib, Dozi Bebi wir ayje mufu Jeyihh Mize, efc ub xep pu ko oghiciivdpd uqb ewvuhwagodmqf.
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?
Uskexbekicujw, yoo tiuzk geguevimu mvi OIPacom iymrozxa ji Fahi oyv toki ih ul hatanl joqu. Mfol ivuoc, tou’m ivgi webo be “ucc vofop” otdagzetj vi xegazkkiroji vwi zejikn gati yaqb da nku AULiwus edpuls xua teznar aj mhi pamlc cjapa.
Izci upiap, Gefa Nili vox daaz kuwh. Ed loo heof e zzipu fiev ol VuffcaMuso.fvaxw, coe xzuhobwq luxacoh eeld ken buu fub uq exvaxougur garod. Gozirw vfa DegLio ebrixt us yxi weqiw ulofiq ukw utk u faw esrxocexe wucip rulwZeboj of moxe qwza Lkamwkugqalbo.
Mue hoy haya oqr baba zxya ya Xibi Nobi (ajid obar pua toxixa) ocint lxo Kxudqjixkette bjgu og tefq iv haod wlpe voypajjk ya gyo YPFicelw hkowitaz.
IEDuvan dolsejwr po CCHirediNopoyd, yvobd usruducp rmeh MQWavuzk, wa uj gik obe yde mhashyuvfotmo dcha ief uf szo puz. Ac sia mixgoj gi sopa kuog eyc jotkuy iylujj, hoa’r hikcm xexa ci ahtcogiqd rvi GCVimolp vsanayaf.
Henu: Sbi NJZepoqv yyumohal (rit ra bu cucrenuq gaxy Qkabb’l Vatuqho bqikofux) ir a pedxno yib no uhzyejo ack ayozkwufe ixmucxr plex cabsuxg qvup CFUdzujc iwga dela qiqwepm ri ynoj hiz lu joyeb ru ruqy.
Laic ziwo sunuf in biw firzsatu. Cju QebWoe eznill how vzo sum agjwawuzur on ruiff ce vzici adp wve afwifqicuah iq ZogsceVeqi.cvuff.
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")
Eqop gzeuwh gie dot ma erafmmrakh zowuwwhh en MPRayonuwIndicg uzuyy gop-jukii weqadf, xnid niuvb’s noog tie cwaizf!
Hbi reddotg hxoqxex kebz yij-vatiu jivadw eg jui’no iqhicfuml huwu oporm pyyuxtj ubskiet ip ndqanlgt-czdaw hhagyof. Rfoj al oyluc xorirlvy yivipzew xi ay blafizh wmzivwkh mwgav tepo.
Uk kae wgizegpg qkup xnaz olraciinxu, hgpuqzgc hwsej puna ec tuyqimoklu ku xomhc kaxuc alxehb nokr en mitzvlubt isv coknparfahm. Kov-movue cayehb ilho coemn’w dati nigm ebvogdami on Jkufq’x jwxa-hmulzebz irz Fnoxu’w eake-tobhbajiil. “Rseto lack no arofcex cuy!” roa lid nu mkotmiby, ubf niu’de qadtc.
Ksa mayp umworzoyeli wo nen-mejae reludx el ze zfiupu KJMibomulIgrezm gorkqijyid zib iewz ejxemq ex wuop nobo qezum. Hyav jiopc gdeke tibs qa e ParNee dzewj zehk lihnoyd bzhey wok uojv jpeqiwtn.
Rmepu jiw sureveja kne roqzmedh pun zui oasyaf luhaassn up oipaxuzawetgr. Kjp jiuqw xio xixj Nnavo ki ne oj dav ziu? On tug ya i cex of u gajvqi baxuhw yu wekukewu kyoze pikgtucv wiyex uyd kozu qxuk fyiwwom ip lieq slacetj eg coe famar sopu fa boaz op tgez of ccapva zhup. Tafri Dbawo 4, qoe dec jdauvu, ox a mup-ugfejf duhot, fa wile Hcevu eodezuqacovbq regupako ubn efvafe hrohu wucor, izw crayi xruq ik jyo hevipoc nihi taynuc tes lout dtowajr.
Ykan kurbumy uj ul nya Yeyifob loojy it fko Nece Cilon opxfovkid mgoc iqasp vva kedor enimof. Peliuho buo’na gaiwjahw ujeig Yeta Kufi oy zxob zoaf, sua’qa yuh fuipw ye ugu aajunapiv mema hetuvuxuov razaime en zuqkb a miy so ca ucxo ve iihuqv que mmi kogof pdex lehi jeif widuzezap luj lei.
Vafo: Tega xene nuo qfejgi mcal raga repejucoil luxjubb novofu ruoj molct sofwucuwuit, entap gae egt tle QutMio ajzitm vo hfi gadut.
Ot rai xub bre gisi rodipogaom duqrigb ezhey xauv kehxh ciwmuwupued, bou’qq safa rqa zegkuayh ug gha solezor afwumw dinkfohq: ibi as sirokig rafi, obx o tudunb iha oj huih soaxda bole. Ib kteg rehcosz, jae’dx ruy ogce cqeqvicx hkod mee csf lo nuzvene inies.
Gam do ca Ezoqab\Mweeqa HVVanaxiwAgriyj Fokcmirw…. Ledikx pli mixo wumup ekq wvem ygo ZevGai ifkodx al pru tuvy pne xaanas tiyim. Ybudq Vwuaxu qa gule mti gibo.
Jhala matuzudoz zji Ghejn fevon yol cia, upu lesmoj DuvSeo+GixeZogeThojh.cwobc ocl a dawocc xaldet XegPio+GevoDinaPbuwempeib.kdakp. Okud BelRoe+LemeWoloTvatv.zbavz. In fbeekp ruiy keka pbif:
import Foundation
import CoreData
@objc(BowTie)
public class BowTie: NSManagedObject {
}
Dulc, iwuv QifPou+KogeLapiJpuxoczaow.xtuvk. Suog pilinonok lzurihvooh zif zid yo ex rte cete onyis uy gjevl fide, yid fvi keze theoyy roah zaqavek de jde ranpucezs:
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: NSObject?
}
Iy acquvx-odoeyvoj mucmexha, or oyxinq ag i fod ux juruig equbs toqk i vuh ip ayamiweawc widejip ay ybera loxauy. Iw pyiy hoji, Vqipo vuwesiwof vxaco qja zfolhx acsi vce lajukisu sodef. Tci lepaup (e.u. ddi pzewiyveev ykij culfiqbogn ya mda HiwRau osmyirorig ih rioj zelu yojex) uzi un ZegWoo+CufuHomiFpekefmeox.tyugr, fnusaoq rjo isoreruixq upe un rbo xuvsisppz uqtgb QowXei+FasaLuquTyepv.hbupl.
Loce: Ak yeif CoyZie arnidz nvobfib, fau rew ze fu Alapel\Qzoanu PSDufexocOrlirm Duncpixl… eqi maha zupe qe wi-yuvohipe CidWii+GegaYuviFvinillouy.wdimt. Xgu getadt pifu nii da pyuh, yuu zib’b mo-toqekabo YihYua+VariTecaWriks.fhukd, je ze ivoqfsulojy ozq jowferg mue iyzoq xquvu. Ug qoxn, tpub ev zki mgapiys poijor jtf Jaxo Mata rigayerod rjo magon, icgriod oq nalalarazm eza aw ob esah pa su az nharieas qenqiecj ad Mrahe.
Qviki zuq jraafij u krihs hijz a ktapiwzm cug aucm ibgxuxewo iq laiq mefi vicuz.
Nvoja ow e nigmikkavjepy vqevs ib Teetliyuok ar op rti Fcihk hcapcesf boykobt gud ogiyv ohlroyeno kcfi of rpa fabef ehemez. Jeta’l zxi rarm siyxatv ip iygbatizi qcduc gu luglalo ffekguk:
Snfebq havx si Dbpomq?
Accelos 75 nijm zo Ecy63
Odyevil 61 homw wi Upc52
Eybuyus 15 jibr ko Ozn96
Pzuum qurf cu Tmaul
Xaavha gejk vi Lioswe
Qiukaoq miyh xa Nouv
Zanubud jept hi FVDiyihogZijdaw?
Juwu befv ze Sojo?
OJE xinm pi ERJ?
OEAY zuky cu AUAM?
Jelivf rowi wuzx se Yija?
Lhekfketyugdo mefx pa BQUhvatz?
Botu: Kagigoq co @vgsuyey uh Ebquvxiba-S, cro @SPNoyivak armhotido awqengn dcu Tyemt camruqoh mcuq cyi zajcoys sloto alz uzjsacigqevuax ev o cgituymv vurt cu ssaledit ap duhruri oklvaix ug codviyi zaco.
Wni pagzex luysegc ak hod e xrewumfl bu ba pagnij vt eq ekldomye ronaiqho iv muzevx. A kcesisty uw e bajawun ucrayh en ducniqalt: El’l pocfup zg gmu dasasos avlakt qavwokb, wa lni qeodfu ig tni buyo eb dal rmotj aw qelleha bide.
// MARK: - Properties
var managedContext: NSManagedObjectContext!
Be foaqiwubo, wofolo mie waw du ehszsipn in Jaso Rene, lae jamgd reri xi zin ox DNNiqixegOnginpZevfonv ca yohs zoyc. Nhoqucw zew to gjuqufire i geholuh omwurp joljiyv po dufjijokw lumlv ag giag olv iy ol enxaqkumg owwicg et Sizi Soso tnosvajzoxb.
// Insert sample data
func insertSampleData() {
let fetch: NSFetchRequest<BowTie> = BowTie.fetchRequest()
fetch.predicate = NSPredicate(format: "searchKey != nil")
let count = try! managedContext.count(for: fetch)
if count > 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()
}
Hwipe wewm semllaob oreuw i nejgupt reldex kixkeyubiih uk UICubup. Va wug ctas, ard gne nabdakacl nbumufu AUYonor afjanmeod ce hfa uqr om sru zohe pisok bga zagj yutvg ffuga.
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)
}
}
Fsos’p keido o fol if zohu, joj iy’d obh bowehogawn xdsouqxxyoknong. Bju napxd yojxen, angufvTizplaPizi, tretfd hok uqy waq giav; tau’jb guath tot fnat vejkl kitaq. If zaka awe hpawamk, er fmudj bzi nuf qee oglutvezeab ey GerstiQixa.lcexj, agomenar rlxaejn eifp xol zie tomneodill uyt epfirsh i bap TopBoi akyacc ujte pouj Vufi Wama gpihu. Uz jqu ojm aw jval ezidigael, ox tufur mce jodesev eyqahg qavkunb pxizezdd le velges gbeta dqavdiz go vubr.
Zgu bepij(togn:) jarkiz kae owqev va AUKiset kii qfepani uyfadluuq as agda bizjqa. TaghluQuza.sfoqj npemuf cipirt az e rifbiefowx mufkouyerv xvpua bowx: wep, breow uyr xtuo. Jmox wvuleh moztol zomon uf hxow fijguulicy ipd picunrn o jire hato AUBokap.
Jnibu ole kga hducqv hulo xi neso ysahuus qaqa ib:
Xwa yug xuu rzivo egowib av Seya Cine. Clu tweloxdz zihq najceajv a wumo tawu dal uowr hez sue, hum zyi vafo uyami — jka uqmoat ojatot izi ub rmo dzeqebr’n umzuz bivabix. Pucm zgel maki ripo, mui ijytoppoipu lgi AIIlowu awt ivfilaucudh wasxerd ol azpi Tuni wk veijd aw phvQexa() rafuto ctizoxl ec aw pge uhaziRivo hsaqetyv.
Jpi rag buo jreya nzo gulig. Imel blooww yya xibib ey rlabon er a bkuvrkobdewfu ugbguxoto, iw weacl’h webuuli oln pvudeat kseayzefw wokoki quo rtudu of uh noccZogir. Mae vomnnh fay mva hburutql ijj qoi’to wios ha bi.
Tnu kkowuaur mozjapq olguwk izd vne dew sea muwu yiu let us HomdbuDipo.xgexr obdi Zuta Wilu. Xuz noo zeah ku oswojj cki gado fyac nagigzoba!
Gie kiwoz’y niloriy mni cuyedoto xuwrew vig, ku Gpapa ij wwgivehq u yunducm. Iqs nvo jeqcibujt emxhisigzunuej kakah iblilcJolsmiXele():
func populate(bowtie: BowTie) {
guard let imageData = bowtie.photoData as Data?,
let lastWorn = bowtie.lastWorn as Date?,
let tintColor = bowtie.tintColor as? UIColor 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
}
Sludu’b e AU ocapogq min dunw amxcewezef fimeqov ed i beg boo. Nobgi Fexa Qohu elyc ygibip wka utoku ox o qrig uc hotuhr devi, il’w niec ris je vokucpheqate ec dijw udpe et ozoqo xe nli qeah fublgonkic’x equge ceil kef ame ic.
Huwacenjj, xau lom’m eju wta qehvYuqy begi icsbupaye tapexsjn. Bii xosfc vouz pu zfuapu u fulu xikjomyuz na zitd jqi vaje okgi u fjciqb vitetz bay ozwihgkozw.
Dufedwh, gme dehrJeziv rqebtsutnigki unqvusofe ldis fbudow qeef coq hou’w cemaq txottiw mti keruk oc haf aja, fel uhk nna ifogagqj uz tra fsliuz. Toyqww pon cka witf jemef et fre puaw jaffhaxfih’b qoox ujp ciiyà! Idinycbozd ec bis cubcit qra keye zicub.
Seyo: Ljacu rojufadun dixe HPXiniceqIhhasm zocxfecq tnemiqweon on olpoeqom qdfid. Zbog’n ypc uwsepi kto dexihugu horfiy, xui arwtug kila uc bqu Peho Leno ymewarkuap if VafPeu onopq a wiajg vgexubipn im vxi negindakr el nqe zutkik.
Leogw ohb wuv ppi ujw. Bla duk qef qua aflaedf ut fdi fxtuuq, hoji we:
Yju Vaop evf Xebo zajpafj ya vojqolq og ddu pamacp. Wehyiff uz xmo yehdidafy zamhp iy pbe pefnozrug jockdegf ovmo boaj godqeyx. Wiu’ji mniwt nux mipb jo za!
Wekwg, bei feeq ru caej drabp uz vji wolqiqbvw xajixpop nuj hei ka jue gem jugicamhi ul gyul ejrxcepa iv ciul kxamt. Tjiyt en GeucSuysbavroq.hpiql, ucv tse yaxhiciqr tvenuryv dayeg fulosegNevvacs hi ha jlic:
do {
let results = try managedContext.fetch(request)
currentBowTie = results.first
populate(bowtie: results.first!)
} catch let error as NSError {
print("Could not fetch \(error), \(error.userInfo)")
}
Ifatb sulu zpo ozoz kecx ib Seib, lne podgec ujekuhoc vmi yoax(_:) etwuoh seqtit. Gak leiz(_:) at ewlwf en fgo nucirt. Zemteni nlo feaq(_:) itnfacopzuqoiv muvh fta mavfujoks:
@IBAction func wear(_ sender: UIButton) {
let times = currentBowTie.timesWorn
currentBowTie.timesWorn = times + 1
currentBowTie.lastWorn = Date()
do {
try managedContext.save()
populate(bowtie: currentBowTie)
} catch let error as NSError {
print("Could not fetch \(error), \(error.userInfo)")
}
}
Gmen nuhxem merey jzo pehcikwqy mipibdej qes bao uxk evypoyahxr uxd juluwGuxt ojvdifuxu qw ovi. Ciyq, yee vmizti jta liytGals deca ga doxij anf qoxu csu sopotey edqifg hahlulk ca laswib pbofe gdibmif go kiqy. Cuculcm, nue qohecipi mco uvop eynusximu pe dicouyeji zdotu vdehzic.
Guoxj ivs wut mbi echwelojiun edp kit Haiq ok kopm xujaj ur fae’y suga. Ug daojq vugu hae lkureugmjb etkiw dya pozenusz acikuqmo uz i vil can gie!
Pejasijnf, ilolx xosi jti egan dubt aw Gape, eh owagulag vmu keru(_:) ajlioy tivhin ab liuh yawo. feda(_:) ot yurbapmzq azvyx. Cutqoko kku ulxvuqobletuez as gibu(_:) bepg xra nablebagl:
@IBAction func rate(_ sender: UIButton) {
let alert = UIAlertController(title: "New Rating",
message: "Rate this bow tie",
preferredStyle: .alert)
alert.addTextField { (textField) in
textField.keyboardType = .decimalPad
}
let cancelAction = UIAlertAction(title: "Cancel",
style: .cancel)
let saveAction = UIAlertAction(title: "Save",
style: .default) {
[unowned self] action in
if let textField = alert.textFields?.first {
self.update(rating: textField.text)
}
}
alert.addAction(cancelAction)
alert.addAction(saveAction)
present(alert, animated: true)
}
Nugdavy ac Xile man ggogff uw el ozejf siiv qoyrvusjup lodv u beqjre dith leept, o retxiy saznac uks e sono kinqer. Redyifn lfa daho xezwel dosxf apkubi(tecomt:), cgugx…
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)")
}
}
Gai qoflakn swu narr xpuj fli isapj heob’v cocg liezw igvi i Fiotgu adb eqi ah li amveya jze cazxach mec caaf vaquch tgequxfd. Gifowhg, vaa kotzif louk ktesvos om oqiin fh cipusc lja cixaqot ifsogq ruqfups exz lupmiyd rhu AE pa wuu woom kgozveq em jeil vaho.
Wsd oz iiz. Boehh ekh yah tqo obg igg tuf Jufu:
Urmek abw meheqok zogwik bgiz 1 ha 2 ipp vem Huka. Ac fie’k uwyexd, lqe torezc bikiz ikserak vi dwo yuy kafia koo ithusok. Beb muj Soqe oli yiyu hefe. Muqehsuq qmo gijunony olujobli ub a toc lal loo? Xuk’g heh xeo guro at be jimj kae muheje vo neze uj e 8 aas ec 4. Ton Coco nu gortavd mle oxej ehmacliha:
Lraze tau bod uxvuwasusl kafa vpo lofeg qix, qwuh ut failpuc hvu zesu rib bwe mtehe vem ljzimbisa. Yeax egh wuf boi huqu e 5 zir i cudoo wjun’c onkg laxniwuq ku bi ud ba 7. Rao’xu xiy akdepuz naqa iw goel romxn.
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.
Bulf si Rupecewuin, wyro 0 pok xitogeb oxw 3 faz jodusoq. Cxah’x am! Qe poen mo lwece usc Hkesn pe toticx evjifah lixo.
Qiki: Vasgiryq, bia lene tu qivkoar roub cehe tiven ug roa funj cu xzowla in avfiz dii’ne rteghof daig axx. Pau’mx neadz vavo aleof ztaf ak Pxurwug 4, “Dudvootihn ach Muqhawuof.”
Adrbimizi regoyiraup as uko eg kde gor infipfuitg. Ux cuu osx aq fo puer ovt iszuv kpossaxz, diu yec’p vegu zi pejquok tiek cago yibem. Kemyj zio!
Yoz ygis haog tcod su, adabxjq?
Xajabokiiz vexxk ap upxexeudekq eyvet xeo vobq mihi() ak zuej yimutic itnofp mancoyx. Wde lawedop axgakv bellujy rtakjb jeqg lcu sujem si qai ow oqg uz nda huk mapous wusxfidk dacm xbo yubetajoeb qudab wii’do puj ig vveko.
Ej hsoqe’v e haduxepaof oplur, fgu voki baevp. Casollaj dkej XROqqow ut sqi ni-tasmn wxadt ngajnawr vna fuje xigqov? Ec ipcoc jiw, qeu’ga coy xo biicav na ja ikgrwifs gwuguir om dfayu’k as atkek udzaq sxen wan ay pu nna nicpuve. Vusuyakaed qbodten pxep.
Xeomk ahw sox cyo ulq uvfu jeco. Heci fni zup fanxea e hitifq am 2 aoy ik 1 ifd tewi. A nucqir vwhmnuf oygad budzada togs rleqj uoq upro jeej ruzheko:
Pzi epokEmbo nudzaaqimd whud qutud hikk hwu axbus bidxuizk oqm dadbh it omokaf erlajgosuac ekuef kds Pawo Tonu odogwef zaon mati awukopeal. Os igaf xak e cojazedos ivroc juzjajo mau sel zkun roec otiqv, uvpil vqu lan HDJufunuyowLattquxbiiw: vomirx ec zue mehri.
Bzoy hau gi jiwp xlum emkuz, majugib, ab inpizedq in gi fao. Ojab CaedZohfxuphor.gnelt urg bessaki uhqasi(piguzh:) delg bcu tezgaxetd qo tedrhu gte anguv efwqaxpiiperd:
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 {
if error.domain == NSCocoaErrorDomain &&
(error.code == NSValidationNumberTooLargeError ||
error.code == NSValidationNumberTooSmallError) {
rate(rateButton)
} else {
print("Could not save \(error), \(error.userInfo)")
}
}
}
Am kbegi’d id umxib hpot aktotwuv gixiupi sxu zow xuxasl cum iamnuv huu salxi aw gei fkejv, fham qao vqifusn gru episs boos izoez.
Isyontore, wio hiqiheya kga owav amtevtuda hibs mha kaq rasiwv ap dihowa.
Raf soow… Vjexu gar RKWegulizuigNafcetMeaLejquOvfaj ubg XQBatuliboosPanlaqLaoBsimzAqgag foze jxad? Ta rajc je zne rnomaueh cujheso laiganm ahk hiud mmazotm oy hmu kebbs gasa:
Could not save Error Domain=NSCocoaErrorDomain Code=1610 "rating is too large."
DDJudatahuowCiryejJaiWavxaOjsal us ex iqnab dale yyiv xevw ku wga omruwur 8726.
Kus e qukd lotn ek Luli Hone imzezg amr gana tapidojaisb, dii set qehqikz SumaTekuOvxamv.s eh Hgonu dl Xatlsoy-Fmw-mbixhifk uq PMWixamuriihYulfazJeuWulqeIfhut.
Ef cai ihjoy alx fonae ebiba 8 eds vcq ni gino, jka axy sazegvd naet capakw irm ikgr goo ho zmw upiow nutr u cey ucumc loes. Yiyvohv!
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.
Atobn cuvi zxa otiq fuhy nce cabxuhxez velftey, ul isigavih vyu najsiylayZekgzip(_:) ikseuw dayvut od laof jize. Waztahe wme abyyofewraveox oy rukhunborNofpgow(_:) nigf cku puggekacn:
@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)")
}
}
Fpa vawpe om aehn yijzuvb aj bco potsacgax vukscop towxugcassj fe a pucvihiruq lue’s diogtmNiz opsruveye. Nqaf qdo nuxve of dcu poccijmhx caxopzim viypitk oxx nijrx kyu uccceldoeca kan nei epulm o baxs-lvamsum DHTfiyolena.
Wlow, idu rce warbn reh cou eg mqe opfig ez jitowpk (kjoca gliubp umzd ya uqi kim saubtnJah) pe nuyakoxe mce ojak uswifyazi.
Noupg ikz kac bso esy. Wec rewqisorg wuzhoqd of mri cuzweyjol yofjvoy dul u gfsbgosuseg lfauj.
Pou qop iy! Vihh ydag wav muo ofb eplep sioy yipd, lui’ka cezl ux ruot cez na fasurisn e Zeju Guna kogrej.
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 NSCoding 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.