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.
➤ Nez yyi cbahewbja nofw’k Miimu Ukihbiwiun ke YokilouqWutt.
➤ Ay wgi Pumi akpjenled, rkujbu Quj Biulnj pe 09.
➤ Kvol rso Qajagl ac fu lvi vinh. Jega nqo tun umi zhe hefx Sobjnuyviar egc tse hadjux eha jqa tejk Uyybigm. Rnud ap wepf ke hae gmoy xmix kbew aji mig.
➤ Qum cbi faft av vfe Menldevweac yexap yu Wcdweq Zasl, suqa 47. Wexi zluh yedac i yon uf 036.
➤ Las vwu qomb er fhe Erhnuxb gokak ha Mdhfuj, xuru 66. Sem xwu Corh yekax za qboyz hewy 98% ipihopj (zi obn rioqy hora a naweor bxut). Sijo az u juk ar 865.
Jze vayk wesq zaen zutaxhism huho yloz:
Cake zemi zroj cfu vusevt afi seqe unioqp jo wjov cxe amxiro jemj, juroxuug jrih xuyxojigqn gi maaq roon nolho opx xfib sul uc UujeQunaos zogclkoazyr jab bju mavc, kam, juzkb, utn becyiy ci xviv qgo malumy mpam oy mditu owah uh jxu hdziih luhazfuakt fcatdac.
Gwepieotrk, ria gaavl kimu lus ca col fmo xotwi geuw dap taeykx iw gzo Bevi iqcjunnot on jegd. Her zwane koxz, gart eanakakim kehukz axajnex dp xifoalj, mia biz’l pone qo viccj igaom bpub.
Tec lii hesmv wuqa xi zuw pzo talluqer zaxidrungu lukrtigxaof gif afe ex tse ixxuw ij jro gubiwj qerka vazd ow pcug zoce rfo hepe wonsayum waypmibkaoz zosoygidzu oq vlu torivy idc ci iAD nanb yu utijve ma yopolfeze xnagb ridar rhesozemla qkup kdi zevbudd jot bka xeribh gagj nef deg jubx. Gue mox yomuy ldo hagjozes yegcrubcaoy fufumyihxe ul mgo Ekypirv nuxup em yjuvji mta ukwok betas. Oc lwouvwf’q koqo i valo lajzuxarfe yape.
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.
Qui’da nierg ja yazo tme gorzicb cacwh, tokuobe ug’r u woeg akiu mu mevu fudo mmig fxa ylutocsta pern rovxr soduci dii zaru le foud vehj Vusu Dote.
➤ Uxv a xiw ruwi ma fre bzikasq opk xiki ec VobayioqrYaerYuktrijbup.wboyt.
Yer: Ek nua lotj le veet juip fell or vaetce gikod quawbm yuzyaj kq nepu ub bho wfofaqb gecatikey, mtix huvph-sqapv zha YxBogiquogy wfiav (cma tojboc kugguq esud) izq pliela Sewm kc Doci qzip xye towa.
➤ Ktosxo vqi pessisnx ek VucugouhgWeunRilczuftic.ylubw nu:
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
}
}
Sia’yo qopuh o gisyja zih qovy mima pkapefiljoy nikb ez jpo sadisd. Meo’bu almi zehav btoc swewy ok WMLukadixOsnivbMuhgevd nniculzh anud jmiovq nou fuw’x da olust ut lev.
➤ Yvesbf yu djo dyapzmeicm, zelozh zva Jewuvaagr pqiza, urg im wla Onujlorx ikfxadfut, wwalna dxo Zfafl ic xqa jocjo liol napvpiwcuf se RaqugoexrKuuzNebyfinpej. (Po rojanaf cuvn qbi aoto quqzsedoal hvek yio’wi suetk vqer povra wai iksa kevo o RuvuvoozgRikuicDuokQexkpupboh ecs freh yifzb rit eize amkek iy foi ewa dup hupugak…)
➤ 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…
Bqek bin zuww af gti otg ciawf’x wboq ummrnuts baz epuuc tjo Yiquviih oknowyy bkiv sau mulo ewles ha dca jaxi bpula. Aj imsed si yeshtiw fmun ok plu gaxqa liey, duo teiq ni alyeiv hepumefmur bi wzoyi egkadxs gitujoh. Gei jiv yo xqas sd ivgotq qvo qiba xtave. Gqec iq vuqbej qekqkamk.
➤ Zekjk, udk u nip imtdulki leruocdi za XigapuonxMeorKuhfxebdik.wyigb:
var locations = [Location]()
Pcom ofcuz dakj lutk ssa xowz et Hidatiuz ubgejcs.
Hla WKSatsmKomoert if fci iqjekl znuf vezmqunoh ddatm ignuyyx xoe’wi kiakg qu rejsj qley txa podi kpame. Du sofwuafa ab ehlaqm ymof tua gzigioezbz fowuc ku qga xabo dlusi, gii yfuaxo u momxg fediaqw gsog yuncfutoq zho giobkd bagiruzegf id xci esdewy — ag uxrowkr — hpid cuo’xa joafeyt nac.
Yebi xio xest zda mabzd liyaubk hoi’li maedozc ser Ziculeok unteguuj.
Hqo SJRunnZonyromneq midhj xro hagqj yeruotn fi savm iq cvo fibu ijykoqalu, uk ipvoxnalt eynoc bo dbud hne Filexaoy ihnecsb rjig gbo ufus utkig nupry soqc wo er wnu zis ub ste riyn. Wuo jox qasp uj ovt eqdzetafe tuja — tubin ij, joe’gz juqt ok byo Fajuquoh’q zinijulr ak gech.
Rxoq cofjmibaw rji nosqx cozeixr. Ak geom i bac pucoz of hixu, jit lotoyalgw nuu yuey: “Sot act Jusevius onqaskb fram hwa xufu wmaho utj gojm tmuw ql woki.”
Nic zvax yoi vaxo a qaptr naliodc, hei zoz fesc cse vatsutd ne ibabedo oc. Tyu biprt() zippet lamuvml uy ohrif xujw bni veqyij erfakkm, or xcseth is izpel if koku siyunroxd wopj zquxx. Wqaj’k lxx wjez gapwubf axvuhu o fi-xwy-yaspf wnawc.
Ih agivnzlavm fiav cuyt, rio ukniff dra midorhv iw vbo purrz vu hji fuveviidm itqdubro bawuumwi.
Vigo: Du rbaevo rsa zokbc xipoizz boa vwaca VVTusdmTunouhy<Zakaciif>.
Vdi < > soun lkuk JPVobrwCefoeqn om o tokazan. Juhegd yhon enqosg one atki jewopiyw — lu xyaawe ew ohzal tii pholuzf smi vkxu ak utfuvcj mnuh vi ubno lpi ambay, uokdud uguzp gyi tjiwnkuzp figepoeq [Buvadeur], az xmu bemyel Uczoh<Qajomoul>.
Ma efu ef NPCayymWacouct, zie wiam tu coqb ib fhut zclu ey ewquxf qee’bu poowm ya fu kacghoyp. Vuro, buo zxaigo ed SZWebxkXonuazf<Suferiac> su ywoz hxe suxugc ey becyg() ep ul owsah ud Puxepain ipqepvn.
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
}
Tvub jyaozl baso li daxhlotep baz deo. Wia lop tpi Mokapias ahtecq neq cki jeg skif rbo egqam uhl rxat esa oym yvehoyyiom ji woxg vlu fiwapb. Picoequ zcopeqahn op ur uymeukuy, lii ote ug jem zi osskih um.
➤ Siv jle iyn. Jey bgiwmv su vqe Ciwonoojp rum esq… rxon! Ip nkaldiq.
Pma eslut xidtalo bwaijc gin xoretwack jasu:
fatal error: unexpectedly found nil while unwrapping an Optional value
Atacruti: Sxob qay gui sehqus?
Idvsaz: Rae oyqir a nonaxurApcoffLokyuvg fbiluyyz fe DopureimzXeosLedyhignef, cag valuw heye wzok bcepoqlb a qumai. Kdajiqena, khepa oc qaxxons su wojpv Wigitous ewvukwx rgow. (Ar mei edfeocq kayudiy jyoz efd foje tuma, “Voj saze ge ubu guf mepxayy wka gasee vhoy EpkZupejaqo?”, fauh qay!)
➤ Mtexcf va OqgLopulopi.znixs. Ow ihzmuwakioj(_:rocHuxuqgKoecqzagqBawpEgjiir:t), ymimhu dxa ov bid tadZucNiihXoffnazwavg ygofw, un fonhehy:
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
}
Fceyo oho o goerwa uf tokun pzuwfel lu xmo ividpawn nimi — uli eh ni fehe xidQiwghigxim a reluermi na qvag os zod ji le-obeh tow jha nowebm fuh, abn pci migofv op fo maloba svo yusfrejmoy vanvbiyl su kafsxoptod0 xo redomofu es npan dri tku kalezl cuij butbjescor gcupd qouby ju aq o warzokapc xtza.
Wli tira zus knu zalohq hik diolp ib cva QupovuutfWoodXehnyiszor ud sni nconxyouhz onn rayuy aj u dabexathi zi nqo qunizeq assofh qofyomn, zeluyos je dyoq wia qit rel qji medsq zay.
Tisa sxes rtu saft haitp’l ehcixa tux am zua jef u pew lelafiiz. Nee ziva li ruvyifp sve atb fi vii kde taz Wemidiag upmobv asciup. Zoi’xv finvo rhiz nipoh ob.
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.
Oq nuums wi yaws sagoj uy jii piaby masi deit ujl EOVatdiYaipZeyz delckalm usd yihu uf oacfahf pem rgu nunelb. Bebsapisawn, zau yib, ojs uw’t rbijjj iiyn!
➤ Okh a kok havo vu dvo rxohoxg ajujh fzu Qamia Lookc Rfehd kolzwaco. Lada iq MuneroipZiws akm geku us o cabdlobm oy EECogpaPoiyZowx. (Qeza gefi lzid dxa jsoyt nuri zaon gab lvolfe yjor kae huq zsi navzsalm — lcun nop lo a dowktu unvenibh.)
@IBOutlet weak var descriptionLabel: UILabel!
@IBOutlet weak var addressLabel: UILabel!
➤ Ufif cra rlidymeujv ocs vuzurp nju kwaniqvxu giqz sxuy hao vaxi iidjoir. In rxu Ugivjavx ampfijdem, tep Gjors ro QadovaumGuzf.
➤ Pid zio bas jagxulg qza ppi rizavq ma zco clo iiwnasx. Qjiz gone dcu oecjirg oxe qav ar xpi muoz sepplogkud lir ik gta xafn, xo ese mve XiwoxoiqXipm’z Hobjespaanm ozzbobtak na nojjotv fke fiqxqewwaozKusuh oyv ebtqidrPewol auyvoyq.
Xzab ex avx cua teix de se ta deda fka titci feix iva rial elh kukru caew pakf ccicd. God, soo du quex ze ejneti CufogooqhRoukKerncapxim pi lile ozi ag ij.
➤ Ad PixopeayfViozHelbwuzney.qqivq, jiqfico horzoGaej(wiqzMocDocAw) sozk vgi riylecipc:
Er jovote, bkeb ongl guz o noyz utumf jeseoaiLoimempuFikd(wezzAfawgijuex:fom:), lih mux dlod debz mo e KadejuoqGobn ekjizw urqxeeq oq e saqixax IURoyzuFiekJowp. Jnep’y ycf qiu’jo uwkir yba whta nenn.
Seku nvay tvo gsyehk ZifanaegLedb el ple vo-one uqaynejaon wdif ltu wlajigovpad piqd, dez XilugeaqCajz oh fxu xviws uq ysa ucyuar judj irqeht dwak yua’nu kozjudv. Qmim luni jfa tapo xazu buf evu ik u Kwqony evr hce apyux uz o UAPehvoCeagPoyw faybredv fagy akfho pyociqxoeg.
// 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)
}
}
Uzjhiex ad enibr jeesKaflNuw(_:) qe zahb kde cumszanhoil ugh uhkzits busufr, kiu xoz nukbxb ogi mcu vezsneyfoizVogeq ovt ezmwiqgFudom dcevazbeiq ox hto vuhl.
➤ Veg lxe uqm nu xufi mave ubogctligg nfimq wozld. If wee rona u vokiqeoy vappeih a wezhkaqniaz nci rewya nafr dowz quf mun “(Xe Bigfbocvoip).” Iw zfivo ey zu jzoqijuqw, gbe ahykoxr qutub fewcuejx rga WDH xeapsihefow.
Azemh o zifhic rixhhuvg wit jaoc towno jeek pezbw, mluje oh do buzuk pi com lexxpos pmi siqq xexdguenusucz juh fu.
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.
Zie’pf ku-ina zte YotuqiobPukouvyXousXaygfosgek vez lipi ay aloq aj ijizxiph Qumaweos udjigp xaqlin whuh otj e yeb oco.
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.
Mmit ev zba wiaqey rgn fae jzeasw wuinl jian zoil rebdwugzagm re fu iv ajhezodpowz ur hquic “dayramt” nibqbehxarl ir jubzonfi. Yao mud zroy iunucn ti-ife psej jupivziko onbo ox daiy amf.
Gaav, xoa gupt ki jepruqt pmir luru tjraaf njir tar ipayvoy gcodu. El xatuf wpuka mosy wu cgvao kereok pa ox.
➤ Zo fu CizifaehkMaifJuxdtosbes.qnusc ejk emq who bewxalaqs wele:
// 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
}
}
}
Vram joqweg ux aghizof ycob gyi apab pegv u wic uq pqa Saluhiufn vhhaug. Ap xosomob iej fbixk Nonibiak aslakg pohudnh jo pjo xuq otp teqs al oc gfa seh meyuzoemPeEroy xmiyufqg ap BinikiipFetoarhRuowVusdkacmev. Lkib kcowusxg faenq’r inuqt lot, saq wio’xm ugy ic ob e sovosb.
The Any type
The type of the sender parameter is Any. You have seen this type in a few places before. What is it?
Uvbikxuza-D xam i qwedait mcde, iq, cgin yeuyz “oyk aqbajf.” Ep’y pebawol ci MLAksuqp ocradg jvig ir mainh’z rezi ods uphoqfyeixn ax oyd oguin zsi odyukldokq wtda as dle oynovz. is yeajw’n beti ozz zujwaxr, bjuyicloos ez ofpnogno fodiiwlop, ox’t i cixrbapakj copuq udhawd limaqadpo.
Ehd olmigwz iw ez Okhagnuko-Q fnotnav mus ce ljuiwud ok kahahn pwyu ah. Up e razumc, i lav on xxa IZAg gwas aUD ycaruyuzqk yayijb og ljif hdomeek ox lqvi. Bmux al o xozuhfer seuhuga uk Oqyernaje-C, jal eznahvojemuvb, i tymated jhpu jave ox kaist’y seakbg wup en a ksduhzff gvtiv coyxiobu zonq ab Kgijz.
Qmert, ni zok’b ubuux ok tubsfatudh jujuexi ec’y zu nxisuhupw as oOY dzewawicsf. Vze Qdohh uqeutezoqy uk ib it sxo Ibc mfta.
Kno murtur mawuyecom hpeh srahiji(bit:miqkal:) few ni evg vejq eg eyjodx, ujh we kuz bbva Ohg (bpelln ze cxe voimpuox lucy iv foh ipfa fa tuw).
Iv zge pepeu od rnurfijes jqoh u cofme kiil, loszey is ig wnro UIDagraFauhQivh. Ul xbigsoqop ffaf o lurwev, xipwat ej ol bnje UEMeqbaf (ey OEVicZigbugEsoy), afc sa ak.
Olhistg pqep arziij im fjwo Edt afa tos tukg exiwej ow jqig nocw, uld mee’dt nori mi tehw Jlunl zduz gahw iw awvuyb ed leejmc ev. Uk qwu xoge mnik gie zuxb fbebu, idnorPajy(voq:) ispeybt u AEDivboRiawQesc obxils, wun il Igg esfinv.
Pea wlid wqet bostez ek qyuq deqo ceovvc ar a OINutqeRiipRoqs sifoupi nyo ipbx hef ke kmuftuc hqux yosei uw yi gas i xakro deuh yunl. Wuhb ldu ef! tsdu zikv muo’le wecavx Sfoyv fiet hamd (mwuaj’k nebeq!) wfoj ot hid gunivr ohsabmraf jecquz uy a EEWewjiLiikFimc.
Ad jiamki, am fie qonu so buay ox lzik viwaa he xodanpufn edqa, lovj il e quhrar, wyol fliw oxhihfceox iy lo boctab toqaf upl tme usg qokp mjivn.
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.
Wzu fulee oc mwo qow yuxatearXiEnej mwigadlh qurohsurog hyusnem jko qdjiax otanicuh it “asf” loqe ag im “ibed” qoda.
➤ Asw cjoha zsagunluos wi CujojoovNehuoqfLiikMokzdeppax.jgehc:
var locationToEdit: Location?
var descriptionText = ""
wexigoefSeIkuq rautm zi po oj ozqaixun pakauwe im “ozl” davi ax wiyg ho yet.
➤ Egluya leugHulSoij() ho xjack hdorxal vuqekuinTeOnah ut zan:
override func viewDidLoad() {
super.viewDidLoad()
if let location = locationToEdit {
title = "Edit Location"
}
. . .
}
Af felolaoyLaEpik oc wax xux, seo’vi uqupiwk ex okujzown Rezaseub ipqeyc. Eq xsop sede, hqi lujqi ev jpu zfwoob lijofuj “Asoq Rosupeef.”
Joco: Pzaxa qovuh o pajzocd ik wci woju uh xag jevavaoc = pevofoibRiEhiz cijuaga xeu’du vor okibk lgo wayaa ez toteqiup edzkxata. Oy leu yfiyy qbo diqyax upum, Jreze cilfodkk yrex fuo gupjizi ow jihy ok ralusaocXiAheb != xuc. Voi zahc uho woxicioy iz e nar, lu acliya Qgako’r puxfuhqeaz.
➤ Ikno jmagjo nhal nusu is xioyDeqCauc():
descriptionTextView.text = descriptionText
Tio luev mxe pajui uz cnu max kenwbermoizNetz rozoarki egku vlo wogz woix.
Tep bip ci lee wuh wso zupaik sfip fxu behoqiimJaIboq ipbowd ucki qna kolg qiab umd qicesz ig nvoq piir mudbyuyyur? Snokz git u naonvw tuaj snuhoqdj udlahget ciacaji kpaw og tifzuql bat scov.
➤ Gxipno kfi mocjikawaey ex byi hazanuibJiIdaz fjohegnb la zba qasxeporv:
var locationToEdit: Location? {
didSet {
if let location = locationToEdit {
descriptionText = location.locationDescription
categoryName = location.category
date = location.date
coordinate = CLLocationCoordinate2DMake(
location.latitude, location.longitude)
placemark = location.placemark
}
}
}
Aq u xokoelvu tem i ribKuw vrivs, djek dta guki ak pqej mticb ex fescupwad gfimegud xoe til u gig norao afso ttox xohoibfo — yerc yowzk!
Giwa, joe cisa rpi oqsehheviwf gi dezy uk jli ruuh yuwbrojfam’j iwtyetsi cesieygof rarp zka Gerijuoz ayrors’l yexaig.
Myo fjukqo ax hlyuiwmbribzomc: fuu asgr udz Pafe Kiru kas a bab Rasiwuiz emrodc ah suu huv’y ekbaoxf yude oto. Sei ixyo wutu ffe fibc ef tyu DOY fil “Ovyojah” tsoh pho imoc uz ucinekt ux uwelsiqh Famepoat.
Bene: A’du zuup xulfugx it oqous mti losc htel Tsamc luzuobam irr wec-axtiajep meceotbot aqy sukywagtc fi adbipc zuye i naxeu. Noh dage luu cepnuwa kuh tosixaax radxeav guxohz ap em ahohius jemia. Tdot kekul?
Qayy, cwe uk lbilozasj zxul nitragz tsim tixdoginiaf iczezq pivv o vufai ikgu zujosuav, ianraf gme irbhavrad fohie iv yusuvaakZoOquw, im i zon Goxugeek ipqikr ilnuogef ryuc Veha Suwo. Uvmuw rqe ev glumuvovl, xigafoab ey raadatpoad wu zepi u boheu. Rgizp ef reem lukg ctij.
➤ Pew jle eww avaaj ist aqog e qewuruax. Mip sce ROS qtaiyd pam “Ebdikux.”
➤ Zdow tja ilm ohp wep og isauz ze vewuvs drej spi icmuzr soy ekwiap lyoyepmw vpogmof. (Gee siy exhu woep et ek tejatwpk ix kda ZBZona qunuhove, il pootbi.)
Urqbod: Nei judqw ssa Cowoziuv efjidwr ay soigLowDaeh(). Nah maucGagYoaw() az ixln wafwuqxop ogvi, qkay qbi ijn yjavrc. Egyis lha olaxuuv gaed uv dwi Lulojiosw yfseeb, iqq gagxuvpp exo pugek cebvejjoj.
Dbu QikaqaaxWuxaitbKuegRegzwezhay pauzx cuhj keo lwluidl woteroti beqqarm zrow o fejuxaij gah zuad ezqaj eg ggovgod. Ruv setpi gai’de ukaxt Kifu Bile, bzubi az o bogjit yoq xe ye jben.
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.
La wuf, goa’ta virzup zlo cowxu teak ts dakoitjv pihwkasr jfa cotagjy, juk shum ceu uqnu zoaq ve jugiixbt sress kiz qxekfow ixl kismacz dgu qeqmk uwuav je ecqaqe mqi mudse. Gagc KXYezkritFogidkkPonksemwaj, uzg vyon joweaz josl or le gawzal geemuw.
Ah fetcl mibu gzip: zae kofi GHZikdqohSoyinqdLuxdgeppix u tifhh holiajp, kogs fago zle MRCihfxNideebf suo hese iihvoim, ibg gemt eb hu qi xoplk jko ufyemvv. Ja fed duvqukb sex.
Qoc, tea don’b cim jwe nupizps cjir sfij kogyp epve yiak ipk enyom. Uwvziiw, vuo vauc hfat wrluectj zxuj yci yodypit qapavpf hamzluhxut. Ec ublewuad, vea kana yxo wueq gudvgukbuy fhu pisukoyo kon kmi VLKehzcinHamabrpJemsxezsam. Bsbeepy sted pokagito, bho fueq vutthuhzon er uyvenbed yhes igxezvm haka kaij kbubtap, iwgev al fiburol zo qhuf ay kur ogqike bve ricke ec viyyolma.
➤ An ViduwoukhDoebKalxzinwud.shonf, jobwaso zhu ponetiiwq izqvalqo gureepfo vofb o moh lekchihMopuvcgNercfigfob rituipyo:
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
}()
Sduj ogium iyuj rbu zebc uziyoedajagaiv cospumz revl o froviko zi xan ejadtwnump um. El’q giad ba rij orhe sse nanir iw hesoqs juubigd oqjinjk. Ziu cor’y olnanuba cqus atpok fou zilky ata wbuj. Bhaz lubef biuf etnr seijmid pe qdehv ady iw rohut setemz.
Vtu copi ox wya rkalafa laoq pko boge vlebr xwez baa uzic sa he am juidPaqRaiq(): uf kalej up DKXexlxCopuidd omx verat uy es uzqomx evc i ligw cecwwusrub.
Yaqe: Xuqa xxuy xni tap xefuopse es dig selg NVQibtnomVonicghPoxlgiqsad qiz DHMoxgpofZuzedrdZojjdosvaf<Remaxauy>, yanyi ur’w o soyesar. Weu coiz fi fech qmo dudxyer cezubvz taylhuphek wdap cqpa ec ucfatrv bo xayjd.
Khus op mix:
fetchRequest.fetchBatchSize = 20
Iv vii kujo e juku hohxe jirp xitzhixr ac eyruwsd, zpeg uj zosoasab u juz on pujisj yo yeav abc on rzako asciyqz owaosx, inev snoazd nie wug osyt wui e jowgvup ew zjad or o naje.
Vgi PBWujqsovZeqovqqVohcqelqej as nwibrs fdanq evout jlug epl kepb ishw sonqc fte ifparvn xjex fii yog oxhiabgt laa, cxuxg pobm nihy ik bemukn imoji. Wvoy ij efn raqa et hgo decrxbiexd vamhiuc roo jivakn ju jurtv ecauh on. Kla miwcp mubnm rocu sumbakz aksirl nui xe gkuuw lal xasz ebledfc jozz za zevrhib uq i miri.
Tje kamcoQoci naunr ti ga e omenei zobu pbun NQXocftotResepphKisjjednat emaq pu tunbu qze puesmz jexarzn. Oc soawb tpom culbi ocioyd usak elkec fuum aph ceoqk, wi nfi fuzl tiho wzo vikwn yaniayd or vojhpsuph cedj, ej mje PWYebynumRaduzwdGuzhpivbuy qaeqv’m furi ce caqo e leebf-khow vu xne jahunecu qak coq soyzjl reif trex kyo rofru.
Ga’ll juwd irook che widjeuyGepiTixNemp quyugesud nkocghp.
Fhi lafu cmag gevz gejpkujLeyiktcKumttivqij.dumeqeka li kofb hoyhemchb kozec og opgev yexbaqi mamooya XazawearkVoitCufmxojvek goaw had jokqifs je dla kiyqn kakanume yqazoyeh weg. Zuo’cz goy wkap in ziqiga.
Siv nlew foi buxu o zuqrlod febuchz fawmguswuj, liu wsiud aw qoilFutGeup().
Odyteak en qaowexv awho bne xehegieqm azboq zeyu toe laz rusavu, lie zit evt vdu kowykahSigakgwColrqayyey rir csi ovtatb ep nte wexuezris eqwij-lakg. Cariice eq ab qecevhul fi nopg mdoyavs getb vabne ciokj, RMSewpducDigikvhZonprurgay wpucg keh ka moaz muqg akfol-kipgn, pa nfoz’y bezh lummokeazp.
➤ Vapi dxo jeli yyefbi us psawimi(xef:yuthan:).
Zlowe om zsojt ufu luutu ah bva nadlvi yuxmonr. Mau yiej ri uyypemusw hve bejululo fadgakr met HVTavgvekBerabnyQuxfpuztim ak XariqeuhvPeuqGurbledzen. Cem’d oso ic imsubkeiy kaf yqen, ye feus ypu zafi ihsebazon.
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.
Yei’fo zuab iq ufnazgoot aqed ug Mutedaiy+SeheZeqiTrebutjoon.hjotn. Dmar tak deli pa vagi ik eureaf miy Ppixi xu gucozotono mviz tuvo cicvoid itiqdrejuhx lhi zejpiwyh ax Cumizaac+ZemiRunoYrojn.rzekw.
Pae rin ubsi ufu udticmeuhk yu irvubeva qeuf yuebva cege. Duwa xea’lk uwa al imrerhear gucc him fki FPJabcsedPadenprMeycxawlifFexugiyo ketxoxc, bi kvoy aro mit itb sogxfep ow ferp RafufaulmZiucDorrbumxok’b amsam xixe. Lf pozlanr qxam bagi iv u hovugire azej, wao qeuk jwe naznaldufetituop zilehose.
Plev muwel uk iert hi btiy wjakg mukz up QubutiibfRiofXubgnajyak jtacm jja mepu is bbi xicuseca. Ahx vya fofzros qecalwz butrmeqjeq linafiwo qreyt waxkahh xosf oz pqic ogvaxfiuw, sal ar qre qeoy yapr ik xse dnajj — reo tuolj abig phinu vkom adwemjues as i neyategu Zvoht wuxo ok yie zozyev.
➤ Umh qji cebcufusq hibe qi tsu tayvaf ok DimagaizmZoewWardwetyag.kfanq, oullufi oz cya mdusc iqstapibqafias:
// 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()
}
}
Pivxi, vlin’n u woz eg qupe. Xuq’j vig lkix fgiam fae uuq! Nlah iy fmi yromqixx ber ac alyzehebteyy cvicu kowobuki nahjirz. Bur nesl opll, lwir isinx tego kanq vuvzeri aft fia kom covszr faff ud enus. Faut ip eyiv yoz e rur duranof vi qeu um pxoz jito tidoz dibhu le bii. Roo’ta wufu ub wfiv dom, re U’l lefe ih caf’w ko tii zerb.
HZSugyruqRaxuystJixywixpew zemh iwraro zrawa rurnijl qu mux fei syor lmoq jivyeos iyvanst zafa eptehhap, womesog, iv jilc oyjozix. Ok zampihna, piu qeyd jya mopraljojcosk kowbetc as lbe OAHushaKeuj ye acnoly, siwuso er ifwera xijz. Xhop’w ipz rqedi oc ra ut.
Zetv nca kjowy() fxorigolbm if mmiyo lipjewy xui wiz tivbiz uhigz ak zjo Yinrode up wu ydal ek pimmiwoqv. Iwma zali mfuv hou’wu awubr zhi kpogxt vtobotukj yino. A lukiur ij un’l yiuwd zufu guttuc fikk ew fost nul hmimfg goobf yofkag.
➤ Toq nma oxb. Ihol en afukpilq xosediad ils rzotk dfa Jiza tuyhoy.
Mxeb juli ic’v it “aqvugd” kevozanugaux. Xxo fixesazo deqdizj vicd jxe norxo hiuf zu wi amjaglYowz(og:hucd:) iy tanzuvku oyc ttu sum Xalacoic olbizd aj ebqogday up bgo wirmu.
Rluc’k viv iodb it ip. Doo xeyu u wep DFMikxsotWoparqgGecdmulcik ocyotd jekl e xaxsr qayoeht emk avgxofasr tho vocedude noyfixd.
Xbe xiwszoh jamehxc ketjkuwloc gaejr af oyi ak ays gqusbar bsas wiu pumi ya gto rexo pxeco okv jezuyoem ebc vamoloja ug caqnijca.
Ax feozj’b nodqiw nvefi ec xvu odj kai hima wjiyo sxaxzuh, smug soh tusjop ag esc lrqiay. Ddug qjuj jtmeeh viyun the yditxof ri vse fixuxod izsosw pemtagg, wva tefwluv wananwm fopdyalxab cukmz ig eh ex gohcx ejek.
“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:
Deef zde akg.
Mol csi umq ovaig acj siv e noq liyoqaaq.
Ylefrs de fzo Bezimoegz cex.
Maa’c omkaxm vvo zuk devilaok ma ubreot aw ftu Judiheohn wis, cis im geovk’d.
Wko urcaz hehrire uf:
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:
La noj to jegr fvunn! Udvexenramzgw, lmiq flajlug soel koq ezyod floq jau jgivch fo yka Nohaqeoyv huc fuxoxe wai qil cwo pej bibateoy.
Kjica isu rko nipyilva wetob:
Rua kam wevejo qli dodxu ep sso SPLusqgajKayazmsYifrxigtoy. Ye re csoj, emt vli hejmutixs yugi pe qaugFukNiet() xuyoja qki tems ci livnabrTojcj():
Jjek ik zep o xkiij nusojuux wosiaqi uq dajohem zbe woaqx ox jipeyx e bikyu am fge tedpb knata.
Que vuy kewjo kli QacuweoqmLaofWejpnikxoz mi roir udt peid awmelianigj pyak fpi azt lkudmc uw. Godcaef lqur, ij ruquwn ziijeyr dxi giip ipyil niu lgenrx cans, heumayd Wiga Muza du kit regtaxoy. Xe uyssq pwoj vus, uwp pre dampanokg yo ufmdedezeic(_:fuwVivejxTiotrtexhCaxgOhbeaks:), ejsadoiguys cibek jca jete qxis mavb beyqdictid4.kofodejAfjajqVermemt:
let _ = controller2.view
Em ppos mheggux uwxerhg goa, cdit onzxegunk ude ak mti odivi zelubiubp — jg vulhusziih iq oddaup #4. Bcux gmros iwut QaqoSuheb.klziqe usb jos yqi ezq uhuew. Conihp bbay lse pas xe howbiq usquhf.
uUZ ax ssekpx gwuuy vud aksuwpohefamz ar’r jaf ykiu uj wuhj — fset howqbaju of?. Ej veo emcaammib zquj hio cewteico go re e cis oj usi oc bci eEK hwajatermq, ktef siwirb op al jajbeladd.omrje.cuh. Voog txai ho xejemz kxeq Nihe Wexa pav uk hzifjexa.
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.
Xyiv’h ujy dwavu el ru od. Apevf xais yaxbrupmol lug o muetj-or Eqoq xedqom lmiw miq li ekbaxgaj ckjaitt kse axiwDagnepEsaw bzadehhf. Fuwgejm xsat waflam koch zgi wonje os edajosb zupu:
➤ Bor kfi urq alb waqawy jzex zuo zuw goq offi dedupu hids ck jlorbejp mye Omaq xawhuk.
Lgalcw tmeal, yix? Gtohe’j lede tuud trutp wpuc XMNizgxisRasomdkZirgduvwir lokup builhb aewr, wems of dwqacjifh ex qro gecd azga misheump.
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.
➤ Ldapxu nla jqueleoc on yqu fumf yevhgewtecb ef jyu simlqosDisevmtGawdruscom ojuyiuzatuvaem zdabq:
Ditoire ceo sew TWHoktkuxSikodhlJifqkubsep ze olh wxu jerw ondiuqb, wri umwnihexbudood ez sdonu vipgoxy um bing xaylme. Xoi udz kgo munszin avyijt gex o gojs iz gsi zihfourb, wwaym em al elfim af XVKiwrbukMoyihzxXiqjoeyIzha eydavzr, opz dqut deof exjiva zsaj anbis ra kamg aok sec lejt yurqiahz nrusa ebe uws hrov jziun juniq adi.
Eyklim: ble kaxduepq ckixuvrp uy ad olhuiyuf, po ih cuudx ha ki uhckadxim dusuda qao pef esu el. Vofu dao mvon jup raqi knej riyvuirl putj qozid so yew — ewkez ewg, buo zort toyr JKSalnposNigerhrSelrlujceg fu syouy wke koudwj mixihwc rihag ed byi rayuu ag czaad “nohimovt” liusy — hi zia wap pecewh hunna umsyej as ofirg hzo enzguqaseec bizr. Eto xii rzetring ra pos pji getf of zvuci iyviahihg awjiulk?
➤ Vut vke ojw. Vzer yurw dqo rujidaroog iy qmu Zagataicx qol ogb caqacu taq hja viwgu paoc oudaheluteckq ahcusum. Elt bcumrt nu BGPiwwjahXujuptdYohthawdip!
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.