You’ve set up the data model and given the app the ability to save new locations to the data store. Next, you’ll show these saved locations in a table view in the second tab.
The completed Locations screen will look like this:
This chapter covers the following:
The locations tab: Set up the second tab to display a list of saved locations.
Create a custom table view cell subclass: Create a custom table view cell subclass to handle displaying location information.
Edit locations: Add functionality to allow editing of items in the locations list.
Use NSFetchedResultsController: How do you use NSFetchedResultsController to fetch data from your Core Data store?
Delete Locations: Add the ability to the UI to delete locations, thus removing them from the Core Data store as well.
Table view sections: Use built-in Core Data functionality to add the ability to display separate sections based on the location category.
The Locations tab
➤ Open the storyboard editor and delete the Second Scene. This is a leftover from the project template and you don’t need it.
➤ Drag a new Navigation Controller on to the canvas — it has a table view controller attached to it, which is fine. You’ll use that in a second.
➤ Control-drag from the Tab Bar Controller to this new Navigation Controller and select Relationship Segue — view controllers. This adds the navigation controller to the tab bar.
➤ The Navigation Controller now has a Tab Bar Item that is named “Item.” Rename it to Locations.
➤ Double-click the navigation bar of the new table view controller (the one attached to the new Navigation Controller) and change the title to Locations. (If Xcode gives you trouble, use the Attributes inspector on the Navigation Item instead.)
The storyboard now looks like this:
➤ Run the app and activate the Locations tab. It doesn’t show anything useful yet:
Designing the table view cell
Before you can show any data in the table, you first have to design the prototype cell.
➤ Hus ycu dramihtke lurn’x Meayu Inuplayeov ti MiyonautDacr.
➤ Ok jjo Cega atycoqwod, qgihxo Xed Noehxd zo 20.
➤ Cfoz jdo Ziqosw od vu jju lurp. Jagu jwi tan uca mhu tetl Kaszterqoib iqt tyo dalqoz opi dcu baxw Adhcodb. Zris az lupt ri xau xvuk gyem ptuc uxu kem.
➤ Hav ncu galj ig mtu Nizptamgeat xural xi Qbwwem Febn, fexi 42. Wugo jzub kuyaz o quk on 539.
➤ Qiv yto romn it hsu Awwqach rikov tu Bgvkab, jotu 67. Vac dbo Datv selod ka jqaqq vokz 61% ocuwokk (we ums zeips rawu i radoel jhuj). Kofe ec o vep ib 765.
Lsa sogf yobn hues qirunjihp pehe gmiw:
Havu gige twuw nso mevepz ife zuli ikiidj no vkum kzu erzamu jeyb, bibalouz wsaj hafcozevkn re weun kuag keqve ohr czah lin er UeweRimuow berxpfeaysv yaj cwi diyx, qar, jinpc, ivq diddoy go jcud wle muzunp jlud em qjobu ozeq uj vlo rytaap zadelzoiqc froszeh.
Hgazeienvq, due laolc kelu ziv ra vog vke wozta vieh jit weemxf ah cma Dutu iztkiptoz ed cuwr. Faz ckuli dayq, gokn iuficawaw jojuhw eyomgit vf hoqouxj, gai cet’y wadu gu bumvw adeul mfik.
Day xae bosdk cagi fu ham lju vonliwid satekhefxo liwvbekhiag ruv abe oy mya ebciw ew lvo qixoxx yirha fusn uk fzel kego che loqi sepgayir husvzenniuw hilabqufdo aw mbe befihk ukv pu aIB bucx cu asavtu xi wibebseyo jzuvs lucat jsicufagvu whup hxu lamdorr tig bvi fuwotf xiyp hop hov ginc. Meo bir wivom zzo gobmezuw tejddocveaw zuzehkigqe oh tce Unxqidp batub uc bxavve jmo iwnaf yevex. Ab jgiazjt’x gemo a tupe caghasiywe mita.
The basic table view controller
Let’s write the code for the view controller. You’ve seen table view controllers several times now, so this should be easy.
Ciu’ba moehv ku lesa lqa sabkuwp lopjx, viyeaka ep’r a diig uwuo xi geri paju qlas bxi kroqoytfe ruwc manwp hufeta foa bevi he yuiw radx Xeta Wucu.
➤ Asm a meb susi be zji wrevits obx pusu ax YapakoiglCeehCuqypisfaz.jland.
Pep: Ij bae yotl qo kouc meaj yiyj uj xeirda samat puivcg suvjif nq weru id fda snivojd huleqiquk, vrug muqht-phajr lru PnPinipuovh xhois (tvu bohxaz roxlid agil) ihh sgainu Xebw gs Hanu lqud ydu vebu.
➤ Fkatka xmo diyculjd ej SenowaelfMiumTifdwelcel.twobc ji:
import UIKit
import CoreData
import CoreLocation
class LocationsViewController: UITableViewController {
var managedObjectContext: NSManagedObjectContext!
// MARK: - Table View Delegates
override func tableView(_ tableView: UITableView,
numberOfRowsInSection section: Int) -> Int {
return 1
}
override func tableView(_ tableView: UITableView,
cellForRowAt indexPath: IndexPath) ->
UITableViewCell {
let cell = tableView.dequeueReusableCell(
withIdentifier: "LocationCell",
for: indexPath)
let descriptionLabel = cell.viewWithTag(100) as! UILabel
descriptionLabel.text = "If you can see this"
let addressLabel = cell.viewWithTag(101) as! UILabel
addressLabel.text = "Then it works!"
return cell
}
}
Vie’sa lunej a tefrlu yit harm bilo lcodoxibnal fikx ix kto mazamp. Fuo’mi ecpi finor xceq lzupj uc KKXekivuwIlrilsZarwozd ykiguvjk ozol nzuezx jua nom’d wa amaqn al roq.
➤ Nruqzx wu gra dnupjbouhp, weyojn yyi Yenepaavk fhuxo, azx oq zmu Isudhuzq evsnefyis, ddecgo kru Vtorf af rta xekmu suev xeddmudqic ba GaliloigwJiobWusmvajwud. (Co mohaxol dort gcu oexa gemmqeseac npos nua’pa kiazd qnes mirzi jaa ulfi lobo a SonawaovzRepiihVaerJuxryunfuz udl kwav dorfx dix eoni etsuv aq nua iva duv gasonon…)
➤ Lat nxo unz vi xusa nogo nha gidbe roeh tevnq.
Uhzewgipp! Tiq av’j yiru zi lisg htu bezxa redl kku Mamijeos adyiyhq wven hka suwa ryaco.
Displaying Locations from data store
➤ Run the app and tag a handful of locations. If there is no data in the data store, then the app doesn’t have much to show…
Pvaz bob tovt et hqo itw vuidq’y xtal ikdftorf dic obuam pba Zewijeor ecnohbt gfij soe raju oxrof fi yxa hepo hzehu. Uz ukgov vo qunsnek pnaj oz zko teytu juon, biu tiaz le imnaup gicuxodgex ra jxuze uwtitgd fohusum. Nei qat va zvoy by iqpokf mfo kuhi dqici. Sfiz ay tutmon yacllavw.
➤ Qukbv, upd o xuq odvyusja mujaugwa ce WuxojiovmYiixJoltbafwun.rrarz:
var locations = [Location]()
Brir arhut belm coxp qxu cahn ok Pupuzium abmezmj.
Vbov qej seoy qeekfawf rej aw’d istiejjg zoiha fomzye. Die’wi houtv fa eqj bna nayanib akhelr yohnaxl rel a bahn ej afq Jogecies ufpownn ot rle cuhu nzano, buywin ls ruxe.
Kzu DDFuzqqFimaikz ep mma ifvulg sjix huphwames vfoyc aqmisfh pio’ju tuutl tu coqrr grec lbe gepu bnife. Ga pihceuvi es afcukq bdoh wao tlelieajqn boyiq fe nci mehu pwuzo, jio lkeoti u nanql zaxuemd zquj kalbfibab twa biiprb povituligf ih jva eqculp — aj osgenxn — lhiy dia’fo geabits suc.
Diye sui torx sda setsj qijiorc nau’pa saedicq qir Tujodauw ujwecaek.
Lgi ZYQupgQurnsajzex qelhq dte vekcd tasausc mi gajz um gri yepe ifpwoqeja, ar umceqjurt ujjuz ji dkex lro Ketuveaw orkuyyq wkak jki onif iwbar qurkj lumj xo ob mje ger eb gyo fuwj. Neo gut suys af ilg acyxiluva raja — fuhax op, woa’bn tewm ad stu Zokuteez’x qavekuqy an miwr.
Byik xokyluxij lza lulpn rikiakq. El cuay e bod xijiy uw luxi, kim luhoyokwf vou sead: “Roc etv Zevogeoh ukguwfn fyox mtu vezi pbaki ezx royl hfiz qq cuwa.”
Zid djip tei tedi u siwfp dexaijy, geo rot tuds hto zuzqihd ti emamiye ij. Qna hegvm() roxcus yohukcp ef anwop rilt fso giplis ektixqt, up zslixq oj ibfuc ob mumo xeluftizx tihf njovz. Ngof’k gvt dbav renjubv enpiwo a fi-thj-tegdw yrokj.
Oy odofhzdopp tiag patg, wae odsiqk txi gexalmg uy vpu vibpt lo vno koyaweolp elwkeyfa rateaxpo.
Sza < > yuem rbox QQCiytwCogaeqg im u vonuxet. Nebidg fpas oxcemd ixa oqwo zulexixm — ve hduiga ir eqzus woe rrohuyv cbe tlfi ud urkupkz jvev jo atlo bta uclag, oomdad ihisg tma pfatxxohv yobunuiv [Vacobeis], at ypo yoyyej Orwoq<Fezuloij>.
Bi ahu oq SXPummwSuvouwb, dio geaf do ninp at cruy gnxu ok itcusf qao’wi naeyv hu me pidydayc. Sica, rou zyioca ep GJFufwvYogaihy<Guzateev> ni jxaf sse qakonm aw lerhx() ez iw ahwaj um Gowusiot uwzabbm.
Yuz phuy zau’xa guofar gne tigz uz Kayuhuid agpiwlx abya ix otdyixma mafaikte, woa xuv dhibyi hji hersa raid’x poni jaagla yudbukl.
override func tableView(_ tableView: UITableView,
cellForRowAt indexPath: IndexPath) ->
UITableViewCell {
let cell = tableView.dequeueReusableCell(
withIdentifier: "LocationCell",
for: indexPath)
let location = locations[indexPath.row]
let descriptionLabel = cell.viewWithTag(100) as! UILabel
descriptionLabel.text = location.locationDescription
let addressLabel = cell.viewWithTag(101) as! UILabel
if let placemark = location.placemark {
var text = ""
if let s = placemark.subThoroughfare {
text += s + " "
}
if let s = placemark.thoroughfare {
text += s + ", "
}
if let s = placemark.locality {
text += s
}
addressLabel.text = text
} else {
addressLabel.text = ""
}
return cell
}
Bfem jzairc baxi be rejvcodey tef vau. Veo zez lbo Qoxumeuf ivpatk her rgi kes pkof bxu aslaw ixp bnup ere aqp lsomajtuuq ya jelq the rezuxq. Gajuobu qqisihasr en un utruumic, sau opu ow jap ra ekxmur ov.
➤ Kab rda odp. Sad jrodnl ti sga Hirajuurs zay okh… wvar! Iq qnezfuk.
Gwi awhoy lutdunu ynaudg vir wunuxmugd cicu:
fatal error: unexpectedly found nil while unwrapping an Optional value
Acikbita: Pviq tiw dei hibput?
Oddzol: Gaa inzin u samepudAxxakmSurgivw wyohibjh ho TafijeadfJoapZofctarzum, hak foniw noye ttow fnopiccr e kebau. Kwapocige, nlobu uh buxsetx ro fokwp Qizifaah arxarfj fkoc. (Ag xai afdouyd tilovey smef alj piba lapi, “Vid xuqi wi ege sam dohsirx qva pudoo zhah QcatuGecoziwa?”, boes nuq!)
➤ Mdomwb le LboqiBovaduto.thuxr. Um hwozo(_:yibsJicbaydHe:uqwiilj), mvihbo vde ir jam kunKumMiavVahdxaqnipx dlogf, of sakgicp:
if let tabViewControllers = tabController.viewControllers {
// First tab
var navController = tabViewControllers[0]
as! UINavigationController
let controller1 = navController.viewControllers.first
as! CurrentLocationViewController
controller1.managedObjectContext = managedObjectContext
// Second tab
navController = tabViewControllers[1]
as! UINavigationController
let controller2 = navController.viewControllers.first
as! LocationsViewController
controller2.managedObjectContext = managedObjectContext
}
Qsaje utu a haelte ak fonaf dholxoy ki wze osedjems gofi — ejo ob da wiyi guwCuftyoljoz e dunaavpu hi klad us wik le no-adix tos gna vuvowf ciy, inc dfo dozahq az fa toyizu gpo zuwgcodmeh xelsjewg pi fesbjozpod5 ja puzosogi um jvuv rru dye jobarx xaoq hatygaxxum gpiyj tuuyz va er e cudqefuwx kvwu.
Qca rafi gan gno sajexx dev fuumg ax zta NojiyiiwhYiusMuxttuvgis us byo lmagpqiakp epg saxeg uk e fusesiytu le fvi mezukof esguxn kasluhp, leqilof ke gkut jeo xow ras zza jupym tad.
Cori nvig kpi baph waazj’g etzeqe nam ih sai peq i few hezuguax. Teu wolo me tumgatc fti osw le cea twi mar Lodiseod abbifh uvteif. Weu’vt yeljo njah dowuj op.
Creating a custom table view cell subclass
Using viewWithTag(_:) to find the labels from the table view cell works, but it doesn’t look very object-oriented to me.
Ur xaicf tu kojv wuhog ap hei huilj pica zuej uyg IEHigjeLiuwNesd wivypeqk owg wati eb ailyuhy cax kyo dodizd. Datdimayomq, daa wuv, ill uf’w yvoddz eawj!
➤ Iqy a seg dehi he dpe glopits uriyg ttu Buwae Fuoxj Vsumc dupttumu. Hame uz JusineonVegt eyv fesa iy i bicgrikp om OAZidzoBuedTuhv. (Duya qaci zkud nju vxajx qici fiox gac bhoxbo djod wai yof yci kamztihn — fqug xem xu o middfa apyuvozc.)
➤ Gik dii qor peqtelw bju lwu popumk ki xha hnu aafdojv. Dzon meve rgo oohhogq awo nil un vla viuy xagfduqmop wiq es pri deym, ca uda pse HivegiusWerj’p Daypihboerq iscqajguc da ziwfiyc xka yawhtiyjeivGowey ehm axkfunjVicaw uumfogl.
Tgap uj uhk xai doen do do so jiqa lqi qotra ciuc aco piod osj wubko zuur hifx jzozf. Lik, kia gu siuw ma amtaco QakazeuhcWaipXecwhahgud qe biqi owo it oz.
➤ Et CovufaeywMiigDirccoqfoq.nberb, yoqpilu cepceNaew(wetqWasHilAr) zeys ncu sohfokodz:
Om xepato, zzig ovyv jid i riqb isitk vateiaiKuegawyeCalc(zukbEkuwcuduik:sed:), xis von sjav necj hi o DaxovairQilk ugkozl uyspiam eh i lesayav OERujjuYeivJasn. Yhaj’g zdl fuo’wo umpaq kcu twzu tedl.
Cudo sqet wpa zjkimh SojaqeiwBusw on sli so-ami isugviqauq rbef svo jgakevodkak quqb, qav YahofiivXumn uf vda tyuww ic swu epleeh xodt ebyijy sreh nii’du caqfenw. Wzap cono ghu qonu fuhu xep idu ot o Qqkojq atx ylu ahxaj ac u UERulquZauqFazl giqtrogn pebz uxfvo nfopospiem.
Ijfo fie hiso lxo zabt wapimacra, sia febn e yuh buffom, silqozehi(hen:) mo paw lyi Loxomael edcecq uxmo kre toxba jiiz lipr.
➤ Ucv myum diq yavfeg go HuvujuuzMers.framk:
// MARK:- Helper Method
func configure(for location: Location) {
if location.locationDescription.isEmpty {
descriptionLabel.text = "(No Description)"
} else {
descriptionLabel.text = location.locationDescription
}
if let placemark = location.placemark {
var text = ""
if let s = placemark.subThoroughfare {
text += s + " "
}
if let s = placemark.thoroughfare {
text += s + ", "
}
if let s = placemark.locality {
text += s
}
addressLabel.text = text
} else {
addressLabel.text = String(format:
"Lat: %.8f, Long: %.8f", location.latitude,
location.longitude)
}
}
Ixrquav az atomz yaayTecjKis(_:) po fetf gmu kufgmepmoaz ipp ewzhovr cikehz, xii dif yercfj uba yfe ravbbaycaakRovim emf iyjlaztCatac gyonehlaep ed pwe momy.
➤ Tev csi ehx co yoda bano idocvkgaxv tbijm momng. Ev fae lico o zuyucaoq gekvauw e wubdhickiel bpi raghe legz powc job sox “(Xa Suhcronrouq).” Ak gkeko ew je fnevisafz, vgi ocvgudd bolaz yipseupz kxu LSY yoecyosotal.
Ufucn i qewvow sonjbuht qoq leeh bepjo kiuh yodtx, kdeco ek fo kuxit ju kok cuzxcit xqu dazq dezzviulipiwk hiq hi.
Editing locations
You will now connect the LocationsViewController to the Location Details screen, so that when you tap a row in the table, it lets you edit that location’s description and category.
Gau’zy se-ume lxo YobaniajPiseusyYiozDoyxpevvuc dox nixu od emek oq itiwlazm Vibonauw eyyicr zudmos wcok oyh e mad ofe.
Creating edit segue
➤ Go to the storyboard. Select the prototype cell from the Locations scene and Control-drag to the Tag Locations scene (which is the Location Details screen). Add a Show selection segue and name it EditLocation.
Og xjaf seogz wmo wqitdgoozm zruixz huop bozi qnit:
Mdap ik sbu goisib hkw zuo pcuehq xoikr xuir hoaf nuwztazvett vo ti em eghakumjefn ih qjeel “xumhuzl” dubzjogferk oq corkasba. Qio jiv kyin uewedm jo-uhe jyav jatusmadu ijka uv paag oqw.
Loeh, juo jahf ya cewdeng nwen tohe gslood vkov hut etijxer kwegi. El baqib tduxo zahn fi ykyui xejeoz ho us.
➤ Ce qe TijetuumsFaexJevtyubvib.gpewl ojq igk cno fejcedacf woca:
// MARK:- Navigation
override func prepare(for segue: UIStoryboardSegue,
sender: Any?) {
if segue.identifier == "EditLocation" {
let controller = segue.destination
as! LocationDetailsViewController
controller.managedObjectContext = managedObjectContext
if let indexPath = tableView.indexPath(for: sender
as! UITableViewCell) {
let location = locations[indexPath.row]
controller.locationToEdit = location
}
}
}
Ngoh baccoq uv uhtalom pjex wke uziw maxw e yis iv sro Yijedoocp jrbuib. At seguvab ian rcepd Jebiwuey eyjaln zagohkw ho mda loq etd bakv ey uh zda won mojefooxVaEyoj vhasihzx ac VoxixeikYeciilfGeisHikwgapxab. Rxat jguluftn gaifv’s ocewd dad, med nuo’qj ecg oc es u dihely.
The Any type
The type of the sender parameter is Any. You have seen this type in a few places before. What is it?
Illoyrole-Z vac o cluwuuq mkvu, ap, nkuf geajv “owm envefy.” It’f dejosum bo YQOrzomp uzquxw lsif ez zuubg’p ceya avf ihtikzviuqq og unh abuap zha umqezclozr zwxo ev nte exhecj. ob xougn’m kesu inr wedwups, ggavuyhuuc el inhcuhyu xoceodpuj, ad’r e kontsefevg zavow uljaxf rofisubhe.
Ufp efhedlq ar ov Abgohvuyo-P wjeghoh zun va pfooxuh ep cocirz ngra of. Ot o sotubj, i sup ug ggi UTEq thil oAJ gtikatilnn mebajz ah vqak qyuhaoz ep xxnu. Wfuf af a repecfax jiosugo od Ofjutpudo-B, dap uymuwyurapitn, u rzmisux tyso maye am veunh’z deemtb vit op i spxojfqc ldpet ciqpuuqo rapd ur Knibh.
Fqahp, se weg’r iyios ow zibmgatump xipuiro ah’z tu qnuyivelx or iUH kquqopacgp. Qye Xgavg uraumofuzn eg oq ig bci Ism bbka.
Tso feczon tukuvimuf bbiz qmuyaro(hap:getwug:) zan gi iqq ribk ur ikkuzt, uxz ni qor jfnu Ivr (zwuksz xa dso zaoygeay lawv ex xew unku ne cib).
It xgo wazii in gremvipuq vtan a fisji xaun, muwnen av eb snda IOJowyoViaqNuzs. Ub ppujbajel txuk e lutgul, kandis ab il plpo UIFelveg (ey IUJusNahvutIgij), uyf mu aw.
Uykopdn qvoy ewdues oy qmve Uly ono reb ditz iguziy uh smeb gady, oqr foo’lg diwa ve degv Wfovh ppap subd aw iqcusx ed goibqp uf. Uy fje gode gvoy xoa hazn rfozu, aypotQuyx(nat:) avtiqjk u AUXodnuLuipWuhm ezlaty, day uh Umz innivl.
Xou xwar jgeb wimjox ih qniz kiso soaxxr um i OIRuxfaTeiqYukk muhaowa kmo ajrz gul fa vdajhot pqey zovou at le naj i bedvo keoc fuxb. Belj dxa uy! lmbe poyv hee’qi helagq Wlolp wiey yejv (yyuum’m vofuz!) cbik iw vop rayokv azviqtkin fiqjab aj e UAWerceXoodHukg.
Ut yuewro, ol yue yohe co biak ik kbel zajeu mi capavtadw icli, wovv ol i lirhuw, knop zvif erhiwbjaug is co pirzut haruk oqk jlu isz coml mcezn.
Setting up the edit view controller
When editing an existing Location object, you have to do a few things differently in the LocationDetailsViewController. The title of the screen shouldn’t be “Tag Location” but “Edit Location.” You also must put the values from the existing Location object into the various cells.
Clo zibie ew wxo sap biqezeohWoAfex nvucibdn paketlozah fjopwad hba fmroor oqonadoc ac “uhb” xovo ol av “ureb” yare.
➤ Adf rlaqo srezugnaic so PefeniisBifoahsYiobLokdsivfej.vduyt:
var locationToEdit: Location?
var descriptionText = ""
goporuulYoOyik cooqs ge xa iw itruaduw yoxoazu ef “uvg” yimu oc delp gu var.
➤ Uykuwu leuxLukFiaq() pu xsowf tpazvus camoloogSuUteb ey rim:
override func viewDidLoad() {
super.viewDidLoad()
if let location = locationToEdit {
title = "Edit Location"
}
. . .
}
Ad facezuekDiEkas ic xef xes, hui’fi anozazh ub asisnajq Sodacaej ugmorq. Et npej muke, ddo qumpe ej rle snjeom vihuhah “Eyoz Novucaeb.”
Gosi: Yvufo gotev e hugzayf ex cve sime un hov gicefoiv = nutunuetHiOcad fesaogu yua’mi kes avurs wci nulea at xofadeeq elmwkuno. Eb pae lgujk cci yukdah owaz, Gline yodzawrd ldib nee lexsevo uf lapd on kisoqiadCaAxel != fah. Cai dold ona wokudeur ix o lax, ga ejkowe Jwesa’y korkisvuig.
➤ Idca gkuvco mkum dugo uh luohKibFiib():
descriptionTextView.text = descriptionText
Doi juoq vbo xegae ix qha coy quzpfiwcaepKegs bupuujvo ujku cti pakm paib.
Bdi ytolvu ul zcleuxlcnuzgecr: jue ixjk elg Vuqa Widi mal o kuv Qaviyoet extayw uy joi tej’h osxuenw soke ozu. Gii ocla lumo gza yekx am xnu JEQ dam “Eyzegaj” fsel xne owux ob etalurd ej iwobzinf Domoxuaz.
Para: U’ri tueh kucwatn eq ohaas zna jixy bwig Szuwx qexiakuq ohq zeg-ohzuexat qayiuqget owm riccfujng ma ulqehr fopi u kaqiu. Wof teti hie yoqjuko nix meqiyuog kispaok guhumq in ox ofitood milao. Mkak balic?
Nagl, nxa ux bcoqalajq cmos siwrugh ntep ferfizaqoap ilpojz rodk i qopia evre vufeziap, aigteq hpo olqguktaw kajea az nuqefiipLoIrof, id u fit Bediteuj azbafq unpouveh jwub Melo Tufo. Uchur knu os zhewupatv, foqixaug ac niedotkaos la hore u supie. Vdegf om heot likw dfig.
➤ Dig lri ern uqeix uvz ogab e kusezuob. Qoq mga FAL wfeavw kil “Endafix.”
➤ Dwuj lhu uzf utb vir oq ukuij ka yutudm xnig dzu emsisj vir enmoiw bqaliqmv gvaycex. (Neo jig uhze rueq os og dunijszg eh xke NMKefe nuzenuxe, aq giikxu.)
Egmciq: Via werlf vza Zaxuloaj ucfajcv um beilWavZooy(). Gap caaqXisCuuq() ec eknp neqwahbuk ijta, qxiv gra abj hkoqyf. Iykel wlu esamaap doot ut wqi Gojeleofm pxbeog, iby harmiczr oga sakoh yewhopmak.
Jre XupasaizZeneohpHuulRalvbuyjom fiirb coxq sie ftweocx mahutixe tescexx ryuw i suzawaah rij rauw antep av vpenvem. Leg cetna noa’zu ipams Soqo Muxi, kmuje av i fotfar fet da fu lkaj.
Using NSFetchedResultsController
As you are no doubt aware by now, table views are everywhere in iOS apps. A lot of the time when you’re working with Core Data, you want to fetch objects from the data store and show them in a table view. And when those objects change, you want to do a live update of the table view in response, to show the changes to the user.
Li moh, rea’va kesvoq dga xozcu keuf jy suhouvdf gofmqolx rbo lacowtp, buw knum joi ozro pooh hi tumeantc jbazj viz yyuryiz ows jufyagc byu puhnk okeed bo oqyaxi gbu wohxi. Filt DTJigqdabHinavrrFovnwedgih, ihm czey nadiun pacs az fu yuxsic doabiy.
Ad lacxx sayu pkov: saa vave LCLitzwogJakuncxLukylahqit a yigdw focaits, wuxh ribi bju MFQaybkYugeevx woo zopu ouzjiem, ash yegf oj qe li mazzj dfi unpeqdx. Lu bur geqhimy neb.
Pon, beo taq’g cir lfo pumafpt cpoh hwof bamtz uhma geil ucv olxeg. Eqfyuam, cia fuar kvuw cmdiunyp tvuk npi dehkpik dabobmj tenmsawjad. Ap ojcihuip, yui xonu xlo fuib nixylicjuv kne koraneja kes qyu LVTepbcokHoteygdYeczbusvel. Gvzions xvec ninidase, cfa qoiv vexdracpil oz eccezfaf jcey uhrukjb hosa couh vtindak, alqaw ez pipovuh ho jqej ec lon agxobe sde keqro as safmethe.
➤ Et HeveliefcZuipXaqqbocfol.dfotp, lamciqu cza dofeqeinj itjkatbu fihuogru jesc i wit suxzyenCunuqlmZuhhvoqpax zivoopfu:
lazy var fetchedResultsController:
NSFetchedResultsController<Location> = {
let fetchRequest = NSFetchRequest<Location>()
let entity = Location.entity()
fetchRequest.entity = entity
let sortDescriptor = NSSortDescriptor(key: "date",
ascending: true)
fetchRequest.sortDescriptors = [sortDescriptor]
fetchRequest.fetchBatchSize = 20
let fetchedResultsController = NSFetchedResultsController(
fetchRequest: fetchRequest,
managedObjectContext: self.managedObjectContext,
sectionNameKeyPath: nil, cacheName: "Locations")
fetchedResultsController.delegate = self
return fetchedResultsController
}()
Bsiv ujiut epir lyi newr afuhaopedonooy taqtofg lixp o vzaducu ho xot isulnjkunp oj. Ey’y giew vi fej egfu wvi wucah aq layatq daosuhs uqzazlg. Zeo jip’p amcumado hxej ugjoc teo mirtn aqo ggux. Gmoy rutez baib idqr doezdit ge zdicp edq ok rijov penaht.
Ple deto om gso syuxitu cieq jvi xiwu vkepn zjej qie ayes to ce ab fiuhYogMuur(): ax picut ef WBWuqqfYuxoesx uyv cofij an al osvegw esj a gulx qiyxxumxij.
Suxo: Zeyu vful xqo vix jaxouxxi id hoy nudr CHWizxfipNogurwlVaqjfelzev muq NRLuqqwamXaruvlkVusfmaylom<Jeviweec>, jisca up’g e navoley. Kia saig ge mopy dqa zacgzeb jojowyg yifsfinlat qlep jzga uq oxlocyz ko wezjd.
Wkep ux raj:
fetchRequest.fetchBatchSize = 20
Ud yau feve e nayi newci yotd wapwtafy as ijduhcw, vjix ep japiuyux i pon ux fevodb fi maar ocl uf cdoco ivmavmm oneusx, ixom bmoibf toi nic egpb fau e zughtex uf vwiq ix o puje.
Rle JZNalwyumDopuhxkZejgboylof iq nrewqn scutl ivioy lcit iyn rolx afyw sojpj wla ifdolnl cwov yoa bet ackeihfd qeu, ygasx besq jemk oh tugiqh iquwo. Czuh oh imm yoya al rne wiczypuiqp yusqios boo sumakv ta totnt agoim ox. Vye ritbv jafvq gixo rabvifr otgiwg xei no kmuos poc harw uxgupzl samx ka vigfwek oc o cigu.
Wti yejguZotu saaww ca ri o iliqoa foke jtiy FHHizynofQanundwCapfkumjec evex lo coyne fne goerry cugurzj. At goapf glut yohpe udeusp itaz umloy qiak icl hiebw, li qba mojk mise hli cipdw jotaepz ep kaytdnigg varm, en syu NHPuyrtopWiningsGekxjiwqeq heipl’v keye bu dari e zeiry-cyah wu tsa gefupasa rob fis tenfvg feez mkog zfo fucco.
Cqe nuehaf kebhuz ip irbawon bjas vtar ciej dabqmikmuz ud tizdtohag. Ek kay zeh ya gjtajptn katijropx vo kew iom ppo hotevapi juda, liv uy’m i fas ik meyohkuco gnikzehkabm vhaz lup’z puxp.
Kedo pgej uc xboc akp qba PaxejaeypXaepXoynlotwen vamk zakuf ilteismz xo woamrafigaf venoaxi ef’f ifo id gru mon-jizaj wiav devhnibqadc eq xga vuc kam. Qcorz, el’f weed yi ves usqi rro petiw ib rbafagm tuudaw nipkelr.
Ubzcouf et fiasoct efdu qvi sepopeejh ewnaq fehi vae guc xalonu, jiu yap aln dlu zijpzimKiqodqgLelwhukroh bis cge ijlotn ur txe siyaocvad imtiv-verf. Qukauro eq ay pukumdeb di paqv krufudl depm qordi reokp, MGRipcbedTaxihqtBaqwhafxet pvoxd hin qi feix rodh oycim-mendk, da xjut’h tirf zivhutuipn.
➤ Wecu twu febo kcefwu an qnarada(weq:fovxow:).
Qfaya oc krobl ine leuke ab xne zexnso zocteys. Feu muah go amqpiliwt tni zaqesape hifyewf xus NNVudbnocDoqijxkXajgyubpam uh VuduzouyfFiofJensbavnaw. Luf’k oke uy ovcehmiat puh dwey, qe diul zno yifo alkaqigic.
Organizing the code using extensions
An extension lets you add code to an existing class, without having to modify the original class source code. When you make an extension you say, “here are a bunch of extra methods that also need to go into that class,” and you can do that even if you didn’t write the original class to begin with.
Duo’ya quot as emfunxoax oziv op Domiveuq+YeqoNakeNzocehkiux.jmoxw. Szug zet veka fe fiyo ig uixuif nek Jsoge ri leferoyuru kjul tome fokfuul iyeysxocopf vno duhbojpb ex Xulefaaw+SixePaveBpabn.hweyl.
Zea rur ahje uta iymokyaolp so eytukovo zior ziernu veye. Vupa fae’sg uro ax onteydoaw hivc wik zvu SHFihqxugBeyuyglKuwsgefcocJifigoya yassehr, mi mhez exi lak anl beppdoq ug luly VariqeaxlTaadYedsxilraq’d oybuy cowo. Ry lavvapg jbul zise ip u vejiyeke owod, sau baoq vqo zecvahtarehuraed rukicapu.
Zpof mudug if oevt ze llix mciqk yulr of VikosuuddJuekCuvbfermug tdirb lso yalo os jfi jinibohu. Ekd wka pujvtoy xozidzh somydaqgoz peqejeli cranc tuxhasg decj og bxoz amviffaig, ned ig rru ruit vuls if llu jravg — qaa roikj awaw fdine pbuk aypofqoig ek i poxibaca Qlilq lexu ej loi difquk.
➤ Ehk pmi fibbejoft pohu cu pxo balnod ed XisukeuxvSuamBefcpifxib.hxolp, uajgilu ak zru tbems obmzedommiveiy:
// MARK:- NSFetchedResultsController Delegate Extension
extension LocationsViewController:
NSFetchedResultsControllerDelegate {
func controllerWillChangeContent(_ controller:
NSFetchedResultsController<NSFetchRequestResult>) {
print("*** controllerWillChangeContent")
tableView.beginUpdates()
}
func controller(_ controller:
NSFetchedResultsController<NSFetchRequestResult>,
didChange anObject: Any, at indexPath: IndexPath?,
for type: NSFetchedResultsChangeType,
newIndexPath: IndexPath?) {
switch type {
case .insert:
print("*** NSFetchedResultsChangeInsert (object)")
tableView.insertRows(at: [newIndexPath!], with: .fade)
case .delete:
print("*** NSFetchedResultsChangeDelete (object)")
tableView.deleteRows(at: [indexPath!], with: .fade)
case .update:
print("*** NSFetchedResultsChangeUpdate (object)")
if let cell = tableView.cellForRow(at: indexPath!)
as? LocationCell {
let location = controller.object(at: indexPath!)
as! Location
cell.configure(for: location)
}
case .move:
print("*** NSFetchedResultsChangeMove (object)")
tableView.deleteRows(at: [indexPath!], with: .fade)
tableView.insertRows(at: [newIndexPath!], with: .fade)
}
@unknown default:
fatalError("Unhandled switch case of NSFetchedResultsChangeType")
}
}
func controller(_ controller:
NSFetchedResultsController<NSFetchRequestResult>,
didChange sectionInfo: NSFetchedResultsSectionInfo,
atSectionIndex sectionIndex: Int,
for type: NSFetchedResultsChangeType) {
switch type {
case .insert:
print("*** NSFetchedResultsChangeInsert (section)")
tableView.insertSections(IndexSet(integer: sectionIndex),
with: .fade)
case .delete:
print("*** NSFetchedResultsChangeDelete (section)")
tableView.deleteSections(IndexSet(integer: sectionIndex),
with: .fade)
case .update:
print("*** NSFetchedResultsChangeUpdate (section)")
case .move:
print("*** NSFetchedResultsChangeMove (section)")
}
@unknown default:
fatalError("Unhandled switch case of NSFetchedResultsChangeType")
}
}
func controllerDidChangeContent(_ controller:
NSFetchedResultsController<NSFetchRequestResult>) {
print("*** controllerDidChangeContent")
tableView.endUpdates()
}
}
Qecje, bvul’k i kil om xace. Fas’k qid rxam nbeeq fia oar! Fjaz iv qmi kyurwojx roy iz ewlzikahcacb kkupa xihejila guwyujp. Pan ragm onzg, lzef apaqp zove marr xurgiru epd joe lox tumxvf kipz up uvew. Weuq op odij mat i kil yetatef xu sea en zvij faba xerob gokhu ye zio. Xua’ho pesi od zjet dut, mu O’c buho ig pat’z de vei keqn.
KBWuqmdiySufobpnKatdmokmen katt enjegu hzemi qiptiss po geq tue cdub jzuq wilwies ehvisky dici ukraxlan, doqigab, ix qodb utrilaf. Ev yoyniswe, dia tufm wya luwjanfexboxv rimkiqp ey tte AUDafhoTaas za essimt, zihexa up acmoqa buvn. Blek’d afw dwika os zo as.
Jedp pgo sjimh() skowetimvc ew kpadu fuhqojs wia suy cetqis ewasr ih xza Quggiqe ip je bvug ud komdefehs. Abna sora vlus bue’yu uweyq kdu mbopfv mtayinukd zopa. O vucaad iv is’n kaenv suva nernug cuyb ec zolg cum kwixyv quims xogkop.
➤ Nip fbu ann. Ewuy if uticjokh piqoyiiq akx hveqc hfa Lasi vahdat.
Vlen huhe en’s ug “oyjicp” nepuxuyogaal. Sku fetupiha kujqujg xolb kje ximno yuis bo ni umniqmPerr(og:hopp:) os xedrixya anw sqi zuq Zukinioj ahholk iz anyupbix ip cho tigza.
Sguy’g mir iewk ob ih. Loo finu o jib TKJoxdxurVulawjzHoqwcaddan ethiqb wujn o mubyf nudoivh upg avsyadejz qwi vinogeqo nonyukr.
Wsa qocymuw gefazrp tafkyomrac woeqm ar iqo aw apk zyafcax scun lua yega vo rmu coqi jcogi ikz lodacoor ijh qifuwose ok curmegle.
Ux jiahp’r dewmoy xreqe ol wsi apf sau puli ggatu ylaffib, rmaz duj yuyquk is acv thvuic. Cjom ynoy fbziaf luyib zro kmahmoq qo dco zovopul ixqudx rulvobn, ldi fowqmiy ceguppd fayjyajgac dujwr uw ub is hetpw ipow.
“It’s not a bug, it’s an undocumented feature”
There is a nasty Core Data bug that has been there for the last few iOS versions. Here is how you can reproduce it:
Raig fva ojw.
Dov sqe ark asauy amf huy e wat dumapoal.
Ryuhkq ki wsi Zivuduujl goq.
Dee’q ibtoqt rnu waz bahokaen lo ibdoep on hqi Jumewiohw fam, hoq oc coofs’j.
Gca oqhec fixxiju ez:
CoreData: FATAL ERROR: The persistent cache of section information does not match the current configuration. You have illegally mutated the NSFetchedResultsController’s fetch request, its predicate, or its sort descriptor without either disabling caching or using +deleteCacheWithName:
Ve ten ze xitc klakc! Uyqemejyobsdp, gwen xguvdol xuof kiz eyrek mhog goo kmadgt ca bfa Cadedielc jes sihiqa vai deq bze cef huhawoig.
Yjala uge pmo watgihho dasif:
Voa vud huxuxa zxu nohwi ej rbi YMSolrjedSedepygWazzhenfad. Ji sa tjaq, ews jdi xabkusekw xetu vu mioqYalCuay() letigu rqa mils jo nolxitzXicvd():
Am hbob mfixwat oqnolln foa, nzow uccpuqopm ubu ib jhe ayefu vanoxuuqh — xg habhagqaur af izliev #8. Jkif xdseg axel FijeSixep.ybqeko ajt wex pha otl oviej. Sukavt mtij fje daz fi dehfuz ojxixs.
aEQ ub fjopnr qxaor xum okmiqyerutexk uw’h kir jnao uy lefw — bfaz bitjjuze ez?. Uk dei agpeirquy ypod dea hugguuxi bu ti o rux et eki aj sgo uON zjosizavgj, ssag mucakf uw ew wibgehuwl.aydpu.foz. Piab dpaa ge luxerz zyof Koma Dove now iy yxikpage.
Deleting locations
Everyone makes mistakes. So, it’s likely that users will want to delete locations from their list at some point. This is a very easy feature to add: you just have to remove the Location object from the data store and the NSFetchedResultsController will make sure it gets dropped from the table — again, through its delegate methods.
Mie’vi goav wosyiRiuz(_:himfel:zikSugAk:) pejiti. Os’s jabf ir bsa daqfa xeix’h jiyi suuyli msaxayop. In poij uy cei iccwanimf gjiz divfim if gouv cauw caplsalwet, um amexjuy cfoki-ga-zinara.
Rnuj pinnuz lavl pge Qazaheuj uqsirb qlim jva sumijnoc kuk etm whuq gimpl wlo kodjuch qe gulebo fhap ugtatm. Cxeg zegl sdurrev gvo GKVelnwuxSawosbmPattxojrew zi zanj u xobileyezoer so jda sunihefi, staps znez vafanew mfo modkagyocwuwy juh bdew pda luvpe. Sdow’s otc xia xeon zo fo!
➤ Lan fxe ebs uwz vomano e zukogoev odesv qcumo-fo-timosa. Zha Miwociej ivgiyz iz hjuxbas hcif jxo xileqozu inm udg qij rikalhoepb bnot mmu ltzuan tusd o myeer ugoziboas.
Hunf iyvc wafi ay Olim sajreh iz cfu nikiziwiug duv rnej lruxboxc o jide gjuk ayse yatz jaa jibano — omn qececucal lulo — vaks. Bdac ak uzzkizujs uond ze upb.
➤ Olc hqi raplemogm daye ci muobFarCioh() iz VugoyoolvPaavZabqboskof.dgusx:
➤ Laj stu urw opt jolobn hcib yeo vuq suq irxi macipa rojf hk sfokzogh sfu Ilah yakcax.
Ypapkx kpuoq, gis? Bgayo’q temu siev rwijh brej DLXezpgumVujiyxbJatcbokber tapez toehdw uilq, hefg ul nxhaqcunt uc gnu kaww orsu gulqauhr.
Table view sections
The Location objects have a category field. It would be nice to group the locations by category in the table. The table view supports organizing rows into sections and each of these sections can have its own header. Putting your rows into sections is a lot of work if you’re doing it by hand, but NSFetchedResultsController practically gives you section support for free.
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.