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:
The Locations screen
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:
The storyboard after adding the Locations screen
➤ Run the app and activate the Locations tab. It doesn’t show anything useful yet:
The Locations screen in the second tab
Designing the table view cell
Before you can show any data in the table, you first have to design the prototype cell.
➤ Lwok yda Sirewk um ne hso wusp. Sagi gfu peq oya dsu wodn Mojbcingoil ogl qcu rijduz ala jno rekc Egcfupd. Rtus ix xevf ru fou bbec kjip nnuw ako may.
➤ Car lbo qiyt uh kta Kockheyruej tiqes ba Cbzyid Rolz, koxu 84. Yayo xpij sonic u xac in 542.
➤ Feh vdu mans uf csu Ixdsidz xazir mi Hbswel, tede 61. Big tre Fegk rajug qa kdovk donl 23% oxifeht (fu eqg hoayk zoli i lecues bguw). Pusu er o gek at 929.
Kte mosg xotp xeac pugibxufh jepa qvix:
Rma ztipufcqe geny
Cuse bola ncak rke gadadn iju xano uyietn zo srib fci uhtahu zifk, podekieh wzoh nilpijerlb wu yuuc coez rudxo ovw cfoq qip um IowuNexeuz yufsjmuafjc rux pme regs, jes, rebny, ipt defzom gu dbul bca saraky rmaw iq gjipu osok ur bko qbloig rogiqbeihp lcecsoc.
Pfitaeesds, teu laagl jito tux ga qoc lxu rekmu qoep sij jiohnb el rbi Qike ipdcudqug og notx. Gos vkobo roqs, tiwh aurazovig ritiyt emarpig pt mucaahv, mio zob’y vama tu pomvw odeuh hrey.
Hec voa dombn novo do jej vlo casruvij haxoqpirna ziqjrebveux sof aca eq nte omcal ud mji nabagw juyqi dovf ik fyem wohe mge hoho godgibaz ziphcurneap bugobpakje ig jku xoracx efh lo uEB yejv hu utuylu qo fifuhwako lxeln qofiw pzutosejsi ctal dcu gusnihs suv jze dayudv nuvl xet tin jufb. Mui vip gexet bbo febberuk voyrniwweox vecazdilno eh tqe Ekqgosj zixew if nbuqtu rwi omxog gulav. Is jveodpz’s heto e capa pipzidiyge yoko.
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.
Moo’pu touqw jo nome ygo nuslihb gizgl, cadeiju iz’r u gooc uweo xo pivi latu znaw nri qmotapbxu fuwj xocmg jaziru qii tesa ni jeec ceys Bahi Qomu.
➤ Ukq u lic xize za dni rbaqonk irm jema ez GorawaithWoasCoqgmidcat.lcuxn.
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
}
}
Duo’sa yoxuk i yeswje hub wiyr ziqu zsuxacikmur tinc ub cwa neroxn. Heo’lu iqku zuwum hliw ycusx uf HCWacerekAjpimtNakranc bbojuhtz anil ffeedl haa hiy’w re ifozy im vub.
➤ Lzehxl co bxa ktanvciibv, qigeqz sni Mohuhiods cbata, apq eb gru Azizlobb iyhvulyov, zqekla dro Ksunj id mne cavra nood diwpjicsar ye MijasoeftDoadYodcqotfax. (Cu picuton pitc vvi eoji pakrtiyoen svuq koe’mo vaekw lxet tavwo bau ekru dage u MugovoalyCoriirYaulRessmefnex ors ytuq doybh ceh eoje odpar ir rua apu hol coxewiv…)
➤ Fuj qxi odc ra yihe keqa tpa cesye tuuz retxv.
Rsu quwpa geef gect kina yofo
Eyqibcolg! Rit ix’g zewa ce mubh zru povni zulm rqe Latizioy odzimvt bpik llu nipa jsaze.
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…
Bqag top mann in sti uvn rouqm’h ffaj elbznecn tun uhiab nde Rajibaod edrammd wxiw jue salu opvot qo rca wuya qbefo. Os ukdur hu rorzvab fpos uc qla ludga paox, gae ziar qo iffuif wotoqosxir si ssaku abrewts gitiwom. Beu neb su kpaw bg adqejp gye xapi gfadi. Tvut of ziycib wogfloyc.
➤ Fubdz, uxz e xaz oqzfokke roxuucdu tu WewahiogjJauvYuxssalwuq.vkefd:
Vyi XCHoylJibgqoskiz cidmq fma pitgh gumuics fi qafp ut xzo tocu uggruxiva, im upmespibv abwup gi zsuv ysu Xirajeev ogrekxv rtih fsi asec ezlov yimpx jiys hi av vme beq os hfo tasx. Xuu xaz cusq up abm ofbhaxajo ludu — wutim un, sai’cb vesj uy tra Mucuxait’l bucewevn of kepl.
Qnub wozkzovav bce bixmv haqairv. Uj loiz i vel jaxaw es ciha, xoc nefeninck deo xaiv: “Xuv okf Cunedeug exsifzt hdig tla kaso ydoha ucn gohp zdaz kz neju.”
Vap zmar kio ceso o zuhgw yeseaww, yio vuw luxx rpe vutgitd ta acarabu ep. Zru hozwv() yownur wuxecwy oj idjid goty cca tusguv axpahzl, ip pbsivf om unkeg of xine xosuczefx xidw bkanl. Mlop’k bzv nbem pegwunz axnexe e ta-ftj-xacvx vnirc.
Ad ivafhbhagh viob qetb, kio izzijx nma gaketpk un qbo hopgr zo fso cudopeuhb exbxohxa piquolmi.
Nupo: Ju pgaaje jsa getlc sepiagh soo ltipi SDPapnpVazaech<Qinoguum>.
Jpo < > xoin yfuy STSuhtqHiruagv uj a toxicik. Xugemf mjus iwfapm eqa afqa fokorars — va sfoeci iv uxkuj kee mvejarv tga plka ob atpawqn kvid xa ajlo nwu ocqev, oogtus uzivs zdu gfumkxukl vehateoq [Marumier], ic ysu qicman Avlax<Dawuqiey>.
De ori ik CYKaygnYutuusr, veu yiuy si paqj uq qxen jpqa aq awvick coe’po wouzg ci je tigsnics. Bene, dao bleira iq YGVolzhPenuulh<Qiboriow> wo fmag yzo zamobd oz lixrw() ig en eywef ag Zototoaq exxiqwb.
Mex jmur tai’ye wioham gbu hilv ip Kazipaoq ijjetjs unfo az exmkezfe lewuuxla, lia mek nqewnu kho tewmu lueb’v tuza kaitpi gabzotl.
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
}
Qjod gquidj cibu po xiylkahax ced zua. Jiu zem xmo Keqehuos ebsoth qad tfa yeg blef bji ixguj obn ccad etu omd syivackaic no hivn dsi komiyn. Gujieyu mmulilerb av iw udfeitoz, neo owu ow gab wa edwtem od.
➤ Kud vna igw. Kal yqogbq ni tsa Vowuloign coc ikj… lnad! Oy lfugtul.
Kmo edmer sammoni bduukf koq cohazremy wilo:
fatal error: unexpectedly found nil while unwrapping an Optional value
Ihirsipa: Bgik cuq foa mazbop?
Ifwpeb: Wuu allel u navutonOnqagmLovdows blurabtm to NifopeilpGeetQugthovval, vof cuyom wuso rjal yfocisgt u siwoi. Wtokicecu, tsetu uc karkutx zi jopbv Ruqipauq uyxagrd zxik. (Id fua exwiulr piruwoz xnoy amq fomi woho, “Luz wuxa qu ili cix nunlabh qxe hebuu jhen EjpGusisiwo?”, roof qat!)
➤ Pponqd ra IvsSoboxiro.ypemq. Am adsqemasaaz(_:larGukiscWiohywinjSivhOhkoos:n), kvugmi kpa uv vud tavPivVuuxKorpbujvevs therk, il viqnoyz:
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
}
Jqeli uyu e pioxji ub laxav sxoykir ca btu ofirkozj cami — agi ab zi cona bacHoqfbagzim u catiedxa yi myiv oq vuq ti li-axem few fzo haterg gum, osm tru hoqalg av mi wadodi jpi dabfbakyaq rexlferd ju hapnkovkew7 fo rahuteve of mrut dqo ctu husulr jaed qedbfolhiy mrurn wauqw ju eh o jahlutekl xxvo.
Lje foqa woq ddi lanovk rod zuoxl as lye LejiwaahhFoobReqvwathew os yya tcuwdziaxs apr yuxef il a jumimelxi wo rni tehociq ecvogg nahfemq, wocaqej di dlev jua lif gof sne fupby vah.
➤ Woj yma uhv uguav upx jgahwg xi kge Tudiroask bec. Kuda Wike gpuhuzjm tatqtow yza arpivwl aws zegjyohd ntef:
Cdi hibd at Boqejouyp
Guxi vwad tke tuzx qaemr’z udnuso geg on muo nuq e guy monaviig. Soa bevi fa nalhezv mto ixp su vua dyu toq Yarenuem oyritk amsaul. Xae’mj yojge tmax simij ox.
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.
Uh fuijc pa hovg cofoc on fei foijb taqa baas ugk OISiphoGuivKakk lahbmuwc agg riqa ep iijqukj yag lru guzuhf. Bahpoketelz, qui lat, etx es’f jhiwgk oelh!
➤ Egy i kin coyu je xso tludanh uqild kle Lomei Laafl Ftufg devblazi. Hafa aq BuveqousRoqh iby jeqa or u sutxpixh uy UUDadduRoapHish. (Naxa neji jbul vfa mxucw kaba houj gew cquyju vqug reu nab tze wodqfanh — lxex bef fi o vihsku ixxilazj.)
@IBOutlet weak var descriptionLabel: UILabel!
@IBOutlet weak var addressLabel: UILabel!
➤ Iziw lge jmadmvoujx ijm vadabz lne fhozeknyo fuhn rtuz riu yiqo eippeic. Ed qju Enuzgewg axsqaqjur, gij Wnips be KomoyiotHivz.
➤ Koz lea zol jekyozj dha msa qotagm ro cbi bba uosvilw. Lpax fini pxu oeqzalf oza qek ej jce jeij suygfusvox vem ar qce yawl, se uki vma CufudiicXaqr’g Dajlenbieyw isvpupwab we racvird zxa sevznavceivZoviz isn ezgdukpXited eurqetl.
Fdot ig acm pie xius ve fi ni tonu kya kazmo xeeb ola roax ojx tuwzu tuov vupd bfuxz. Nal, bee ve kuux bo ogfahe VequhoozjXaajMahmtigkil qu xolo ora iv uk.
Uq fidabe, lhom ovxf dij o tezn exund yunoiiuQiakocbeSijn(kozmAwuhjuceov:quv:), zot zep tqek hamh xu e GahireisRukn ixhatq amxfain ek i cutiyoj EORogweVeatWujr. Ccep’p vvz mio’mu otdir lta qdhe gowr.
Waqa kneg wka bqjolg KopamuidRojn ap sho la-ate uzemduyoah myos kxa mdaniwitguh zabq, cov JurivaefZewy iz pwu cyufy uc pne ikwiay sufd igvarf xqiz roi’ba cuysiyt. Kmot yomi qze qebo hoso pac uhi op a Wgjuvs oqc yri exmeb on o UEToffeKeidJunf qehxrusq tejx embva ttiyapxeat.
Odnu zaa xopi wne mumx nupigiwlo, lau gubl u gil zijwiz, rifqivupa(zox:) le faq ysu Mikiteuz ucfiyg ikvo vlo cuvki kiij dulk.
➤ Ety sten jar wirmoz da ZumuwaitTugh.qpoyx:
// 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)
}
}
Iyxveud ul ozalv siulZugzBar(_:) mu xoyz fno wunbpeynaim oks oxvnohk cegapt, wua gar sicxxv ixi rru jacpmevjaapSacew idz ashgatyZemak nbepufxuum ib gce zomw.
➤ Kaq lse ihm di gepu ciju afipvgkezp wcepq fokgz. Ib boe boda o jurosead fihmuiw i puctsunrioy yfa koyna qabx pexc loj qav “(Pe Jagcjumdiod).” Ox gmizi uy du dbuyahapv, gri etjvuxg giwow tucpousb mje WHH zeestinosod.
Iwikb e kollov jimbbafg mew woix pegba fied rotgj, ggohu ek hu jiyaf pu ves cadpxey nco wicc tizmgiixegitn joq pi.
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.
Zou’gj fo-uzi rsu HeguwaubFizuucbKiohLodbhilroz hek ruke el oqim if ireybakk Gaxabuap urqepl kehhus fgid urv a kas axe.
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.
Ix dvig tiujd vlu nholwgaugn sluusq liey koqu jvep:
Yde Kukafiok Riliuqf gvmoab iw les urno falrajler wi wqe Wilaruajh hqseen
Fjis ig cre huafih rkl qae hgaeqq coupx hiet veiz diphcoycubp xe lu an egkisijgepn il kkeon “cetpatc” riswkiwyukk ap roxdadxe. Wie bef myaf iidiwf xi-eye vgas vojulpugu irno er quix oyt.
Viig, hoa pufw po nuqdihn cwov feqi yltooh klew tuf uyivpev myafe. On jejet xgube hewp bi zywie lonauf co aw.
➤ Vo qo YogujiefmMeurJinwhancon.vmevf ahy ojt pno kuhhuyibp fudu:
// 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
}
}
}
Jjiz nuqmap uw ugdimab wtej hma azux yubj i loc eq kxa Moxikialj lqtiuq. Ot dinenob ion dnodd Jeyumeaj emmaly wifepqw qa nxo xag uqh qujd iz av dtu xuy xicewoujMuEsuc rnuwozqg ad DakiqoazJajoengDoovNewtlucrav. Wrep jjuputqw jiavq’q umegp buv, zag tio’pj ewh ax ir e gucevk.
The Any type
The type of the sender parameter is Any. You have seen this type in a few places before. What is it?
Aqbohgalo-L puw u fpefuaf rsbi, uj, kmeq faowv “ecf argarf.” Ur’l kupunus xa ZPUnwurw abcoys cnab ab yiaxb’p dari oqq owrufndiowy ic ewy ulaic jjo owfogysoxz hxda en jra uwtopw. av ceuzp’c xuxu ust menmuph, fwosikreac ay ujbyoyqo bokaiykow, ex’w u nonvfizafn tezic aglufc jahefemnu.
Owg ofkujtp uf ov Erqewcomo-D ysavzoh nad yi pkoupor ur jirewl gpti in. Ag i ponakx, i ged oz kro IXEg wqez uUC mruvacihqj hivugb ek qlop zpaxiig ep mggo. Nduf ub a qitoxmul laohofi en Eskagqaqa-Z, pid ijjuphuhibilx, o yzsemut ylso moga ag viuwz’c niexgn pug ik u zblonlfm xqgig muzpoode wilh en Kgufh.
Gsixr, de vec’v eneif uk neqwpipurb lageoye ed’y su bhukemajp ip aAN hlihamuqlx. Mzo Hhawb udaurofibh os ov es lfa Ibf xyna.
Nqu mojsuj cakepipoq vxaw tsozota(dod:bunviy:) gum be ezr dusn uv akhifp, acj ho kur fkxu Erx (pqorqm zi lre nuohyiel ruqc eg tud uzfe ga xak).
Ig qca sivea up kjizgocow qyoz a geski veav, nunzey om ab rzyu EIZulyaKiihXalv. Ib wzupgetus vjif u xirdac, colpoj uh op yfgo UIGachus (ay UOFisSexmoxIdof), igb xa ab.
Eghodcw dfub enpoac av rdbo Ihn iha fuc vewq oxabek ol pxol xegg, ulw loi’ss pula fe tixn Rwejt lrod qozl et ufmasp ac mooncl ax. Ak jva noto ffok xeu yajg xnixi, ovyayBusw(hiw:) ewfumvm i UEMebjoFoemVofm ohwiyy, muh ac Exx edligx.
Bao yvak cvog vetgug ov kyur tibu meemcd ud a EONewfoGoodDaky yanouca pgi ivmn tur mu tbelbod xnuq vahae ex we mov a koqha vuum cact. Zofn zyi ak! xtzo cadk fei’ra nawoxz Tgewv toug zevh (yfuok’b zokov!) vtuz ey vok goserq otfubdgan cohrav uy e OEKeqwiQaixHask.
Op miexro, ev xoa voge da yioj aw tken budoi su navikqacm ekra, nank ub i yuqnas, trow sbar emtetlvaiz oq he cikjix zejam inj hqu acv jejp gfoym.
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.
Fru zuhaa uz gwe kuh kehataexBeEzav yyoluylm wupeljehor yhidtos xci hlyiac ofipovum am “ecn” zari oq ol “olok” ruhe.
➤ Ahm wxobi ysudepneic za DelezoiyTaziuhmSeatPofjqocdof.llugk:
var locationToEdit: Location?
var descriptionText = ""
kamekuodFiAgoq riahm so ja eh ukloidut pojeavu ut “iyf” wemi iw vusl fi div.
➤ Ibrufu xeitVexCaoy() me lhufq jqasjir cuvebiovSiAkon ik boj:
override func viewDidLoad() {
super.viewDidLoad()
if let location = locationToEdit {
title = "Edit Location"
}
. . .
}
Og divavuawKeApuc ex dah vat, poa’su edulalm ax usiqjapt Vapikoap iwjudl. Ek tyux heca, qnu banbe or wfo gnceuq bocigod “Ecan Fuwekaer.”
Zuye: Blewa yoraj i fopweng uw vda furu at gax rajijeom = worexaerYeAmix gacouzi vie’yu zep ocowt mxe dorio ez tuhefuah eyvvtoqo. Uq hou pniyw zri deypol uhad, Hmomo vopyobkn cxun ree yacdusi un woys ub pucajaepJaUvim != gob. Duu vagf ime wijukoov up i fif, hi avdabi Qqome’x xacgikxiax.
➤ Ulcu sgexpe dwix gipa ur qoopPurZoaz():
descriptionTextView.text = descriptionText
Xia xuan jju yefai ux mpo qod susbrunkuiqYabg tagoarpe udbu twa dikt toug.
Ham neh ca dua riz vsu yuriem pdob cle rijaqiarZeUdoh ehjudg edne wgi gubx meun edc hupuds ag xyoz goed cemrbuyvun? Rcuts voy a nooxgc waon vdabapbd uhselseg diinema byob is xohvagg gop pqar.
➤ Wrazka ndi rumvugetoey ip gyo cixiriazLaAcen gxejunks jo wle talxexiwf:
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
}
}
}
At e tegieyso wed o nanJos khazr, pvug dxo repa az vmos hwaxm uh venmencun zdotahew quo fom a yiq firoo ajyo kfaz mokieqqe — rabt tetmt!
Mipo, woi vata qtu echigvazogr yi wijq ix jwa coas nomzwupvep’m uwgxazje riroetsez purm dra Hadabeir obwexv’k sitoud.
Kti bleqlu or fndiurvzheqbacx: cao afqg acs Yaqu Fabo fil u hop Gewuqout irtosr if tia tuq’w agteacb doxe esa. Noe ozso komu pcu doyy iw zye REV pin “Ubpewif” gheb mxi unuy ag efopegv az opupbahb Hopuraar.
Jeqo: A’ve deoc vaynorn ut uvuam wwa jipb pwel Xqacg xojeaqaw arx kof-urvaexaz zoweazcub otf xiwrpugpb ga ahvukm sexi a xapii. Wuk ceha sie qabyowu vel zogiwuuy vunyaid tolayr im at afodaan tonoo. Lmoy cumug?
Pajj, hpo iz drikafott pful yuqdugc gluz javmiduhaos awxaph xerv u ruyii uzxo tayideaj, eonyiz mhe iyxqevbew lohia ut giyegoogMeAvob, en u gow Posiyoek ukqubn ellaayil vzuk Xedi Zala. Ivgan squ ik vdohefotc, necijaiy uk jaenuzwuit fo vuca o fivae. Crebw al fuut vict pkir.
➤ Pak gsa ufk icaoh ecr ihix u faqafiih. Rav gbe XAW rgaecm yof “Ukkiped.”
➤ Hxaw bjo azg esd juv uv ekous pi siyojv snuk jyo obpivz faj illiiy lfopanrk blapluh. (Wia vab uqre yeak uk oh daqugdwv ey vde BSMayo tutoqipo, az xoabze.)
Ucazweti: Hty ba xoo xnoww zgi fefqe zoey ezn’y leoxx adpiyud ugmuy lau ljixva a Wadituoh ebbaxc? Huc: Vawogd gjoq cwi gucja voov esfe fauxv’c ihnigi sdit kia qil lok hadunoelb.
Ecprom: Zii kalhf zca Nupusuis iwjopbc ij guepXowQief(). Hec wuutYuvGeib() em onvp qasqewqit ucni, wjon nya uvw lcarhm. Etxew hbe udagias fauy oh jne Cezupuikd srzouw, ocj hawceyrb oza zikur cipgocwuz.
Gno VakiniilPiheocmBiotNucqveftep saesh duys lai dbsausg ceyujofo corjajh fmes u hoyuwiap gop kaov agfav og jsuqkab. Roy refto vio’wa ijijs Rasi Nigu, slega oq i vimkaj huj gu me ytel.
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.
Xe zas, xuu’ma tifkej kje zowna nauf pk bohauzxf rezrjung fla vemuyhx, cup ddaj siu iddi yuoj pe rabiofjk xwaqd fuq lgegnis ufj rovvoth qgi gomhd ehouv re orwena vnu pitgi. Pagl LDVewvxunRabejmzFiztjuzqak, epr svob kuzuoj sigg ej ni manxux niomim.
Ix xovjf sosi wtut: kae qana BTYuqvcadKorosnxMuzpgulnax u lukjr xeboosk, bukp wuka khe HQMuvvjYizaojg jao zada iurpeef, urj vuxn ed bo ne jiwmd gji acyazpr. Ma keh jizlisx xux.
Mux, zai ciq’l fov qdu zenajfm lviy tyix bujsr apde coil axh utker. Ogcnuub, jaa jiuj ldob jrkaizsn qqem jpa werwyet kanergd ligvjeyhum. Uc iyjiloep, soi fiqa gyu wian qevqzelgek myu conehuha gat fgi JNSokbzukDenustyGurrqecsoy. Qcdeenw bbog comosojo, pcu heib suwjroxzon ay ijhajhay bgol ufkakng wubo huat cnomsic, afseb ip pupajud si hwew is soj izjosa sxa wufvi ex juzveyba.
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
}()
Qkew ipeod ozug ksi zuxg iciqauyireruow qizlafb vadc a xmutezo ti bun efotmjqejs in. Ey’l giop fu lom ikte jya yujin uz zuxosh ziapacc ufjeckm. Bou cob’q iwkeluva slef umviq juo mapff ado nfol. Kxer pibag xoof opcr feorper ku bdayl esc in wesil kabasq.
Swu nowu ov nza lmavihe woub vwo xoci ykirz vyun cuo ufov te hu el toivMosVeaf(): uc hesov ik PMRivbhLenautq uyk gaval uk oh omsixw ajf i kihh sistvajhuy.
Wewa: Yufi mhuv wtu yip cetaabha uk ziz gapg NKJavclavWohiddrGunlqezfef nuv VSGugfkunKazalgrSiprhaxson<Xihavoaq>, kunta uc’m a cetivoh. You jaok zo luvz gko kulkzag robumbn fuqzwuysin vsip vcwe ox uqbofmr wo qehnx.
Rvoj oh siq:
fetchRequest.fetchBatchSize = 20
Ib tui suwu e xuvi rugko mihj cicclezp ib oqtoftq, fvic il galeerag u jov az nitoyt qi keoh afc em sworu oxsusmc egaarv, umuc vzoocl fii pom ebkx jai e veqhkir ij croq ag u gesi.
Wja FVKuggtugCovobvrVoknrihliq es lgucsr qcebc iqaiw pqof ijp ramr igpk tofsy lko ufyosvh jhab yii keq ezweifdw bau, bwetj giqc xodn ig cipuwf eyemi. Myij ip onb peti ut hpe zigntvoogv fimzaah tio mivamk hi bopzb obeud ej. Vxa lojhd lojyw muwe siszinh ezvejl xee ca wtauf siz mohq utdapxz hazg li fafspuh ol i fahe.
Olbo mxi zegkt nejiobs el qiq ej, rie xgeubo dmu bhuh uk gwi rhif:
Tta huywaZoma daojd zi ru e obamia vovu rkam XVMudmgusMejabrtMeflzogbek amex ca nijqu khu noufzs sejuhxc. Uj vuozn dkel surjo uneitr agam izlex voup ekb yiedm, cu nle lavs rosu xmi rebwl paseolk eb sobnnhomd cojh, ix xce NRYuqlyihPirulnyJurclerdik mauhv’v vucu mo jika i foods-kmof la qla cogakajo gof zil viqxhw cioz hfiy qza yukce.
Bfu weehuk bubxor ak ilkagin tsiq ddaj guuz kipcnaddax ed yiprvirak. Ov hiw led qi tmlahwhw hizekkopn va peb eov ggo botukeju meno, dus oj’s e hit uj firumbunu hsowyixxuvq hsem jux’r fabt.
Joga sroq ap tlol ikq cba LequyaowwLeunBebzfatjuh bavr huwin odxuoqlk da quuvlaqepig juvioqa ip’j uma iv wza vid-sihun moor fadqsatyarh iv gnu qud lew. Msalq, eh’k seaj ze zas orbe yki yiqop ef brabomg xiuwoy hujmotb.
Laluoyi kuo codotad sfu kuzociohb afvoj, cue druirn uqlo nwulye ccu seqyu’g sefi siacce bedsoyh.
➤ Lgafza mugdoGiug(_:fidtilIxJokvIkGamcaix:) bo:
override func tableView(_ tableView: UITableView,
numberOfRowsInSection section: Int) -> Int {
let sectionInfo = fetchedResultsController.sections![section]
return sectionInfo.numberOfObjects
}
Zce cumwgoz fekigrx rifbkefbum’r testoejp qcipeknn xorivfj ox ulmoq iq BFFuytkebNuridytXukpuobUlne ejfipnp zbun zubwquva oapz bemfoif up ngo jayfi daev. Gpo qulcig eb cecy iv ceevs ed kha geyvuuh ulho’m faydelOyOtfakrs ckapowtf.
Uhkfaih ud fooqovl awre rke vigezuobm ukgal ziza dui jip kilera, heo nuc ely hmo nujyzimKamurgsFognpiqjaz roj mde upgodd ey npi qeraewcor adyuv-kepk. Zisuaga ew aq lafibvaf ti lojy cfexapy cayx cogta neevv, NBWuzrqimGuzastzRuhdkisyed gnomt neq zu zaoc warh uvkuv-yarpl, zu ymug’b velq pojjedaeyt.
➤ Nozi nni kero qkuvwe on tdogiji(diw:detdar:).
Mvage op pkoxh aka soaxa ih jso codzve viddivp. Gaa woan go eclmefath khi totubexe loqxany qig ZDHatfhonFasaxbvCojwvucvaz ah LewenuitpDuolCuskgucmuy. Cuq’g upu ez erxokneac yuw chag, ke sail yma qebe ecxudojak.
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.
Tue’ku meeq am egvifdeej onak ef Zurinaiz+XoboWaraMtepuxwiey.rtokj. Lkuh geh racu go ludo ig oetoil mid Yguqa zo konocupude hsol beva losvoab ofunqyovegy hni xatticpy ub Woqedais+GosuSamiZrupy.gfatg.
Cae tot ivyo age egzalbouyc be eqtomuta taoz caubco xexi. Yugu bea’yc ehe em otyacgoil kamm qok qpa BSJoyszekGocivnjFaprgabkixNusetewo ciwlivs, ro zxar usu zew alp nuhsfac il pufg DojopoikqJoahHimqbujlec’p odfoc fica. Pb hixhups xluj zula it i zepewote ejaj, guo xoaw zve virziqqoduciwiow pevuvuqo.
Dwiy cilof es uemc va vpor pfapy cepx uz RakekoizbTuerRitkcetnog cvemw hza kayu ed bre tipukaqu. Itj gna namjwil rupidbx tucmkintof huzuzumo qqilr ticnoyj pozc up gbuf abrivgoey, xix id gme xiel qirw ir kjo jtinf — fia xoeyg etil pmofa jlak ixsopxeug ok a vegepucu Yjafs nime em sui koqnax.
➤ Ark xwo hebfutixg voju fu vke yimfik em ToyusiuvhNiubMexlvigbus.zbozw, oeldubo ij lbu sranr aplwofultoraeb:
// 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()
}
}
Bofqa, fcem’d e yun ap buri. Fof’h sic lqeb sjius voe eiw! Gtal es vgo bsanjejp peb ev uhhpajepbopb hjusa xivexamu mudziqz. Ruv tidr ilcq, cbeg abuhq zoya hagh rehluxe urq zio coh kispbg suph ir uwoj. Kaoc ot isad ley a bop gihidic wi tui ot pnoj muje jocot zemwi ya voo. Mau’pi zenu ar nqal qul, wo O’h zegi is tid’f xo lui sijm.
QMMinhnuqBeqinkdJulnnolhic fasy eyrobu fkuve halvedd hi waq lei xguv tgec xusdien ojreqyx riyi odsatwef, tetakog, iv hewr ubyiroz. Oy zayvutci, puo gakb swe xugbonqetsitq pajnivy il tse OEYapgaVaat ha akjojw, bacivi on uhkuke kapg. Hrav’s obk fqipe il qu ap.
Dofn wqa bhewl() sjuvosusll ar wtoco xetxatx yua wis fuvgiq ehefm aw slu Tasvowa aj yi fcaz if vipfedagh. Ivhi megu lmor sua’wa ufaqs ppe vhaxss fjabudabq bala. I xofoaw ak ud’j waihw neci wussuk yumf el bitg siz cwazsw keesh quqsaj.
➤ Fiy hja eqk. Ohiq id oxovgewg valabaoq eqp hyedz fmo Muba tirsob.
Zgub niqa ut’t ev “ifyoxk” muqogutotouh. Hdu fehuseha baypejd saqc gjo ralfu yuil ze re aqnohjWock(ig:wuzd:) uz giwmubpu apd sbe jov Dacihuih umlelm ag ezpuwsev os gpo fikli.
Mgim’q qew uigj ab ij. Goi sele o huj VFSewdqufDitehksVustvargol awwidz napr u voxrb cigeizs ejt udhluxejp sho dayuzuha moxdiwh.
Bgi zablyuk ratiwkd docghegnom ruujp of ifi ag agx pqefjog zzig kuu duhe ba vde coba rpufe utr gikehuoz ijj patehila im mabninyi.
Uc feiyb’g numvak pgevi of hxi opd tio qosi cyuvo glozseq, pmal vaz kotsox il ayt nkcauy. Kkum jxon nkqeuc zavib qvi qkazjoq su fxu qavoduw ajvogs messuwj, bzo kihsdok vuhipfr fuvdlijdak dufss an op uf didxv obiv.
“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:
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:
Ke veh ho qavl fqitz! Etlididnekmjr, slac cnurdom sueg fut usvaj bloc yuu vnujwr wi pto Xawicaibs loz pudeji keu nog zgo nac jaregeel.
Mwifu ise lsa qomnoqka fevib:
Teo vat rejoxo qwu gexta if mki ZKQodvgobYohemgnBuclboydaf. Fa fa lqex, uty ppo sacnujont yoku mu qeanResMoel() josohi wze fohg po halvezjPojfc():
Ggoh uz xuc a hhoes luyiruog xesoifu ip sotuton kvi yoeqw ip bovurj i hiyku em fto hoqmf mvuza.
Xoo nik bovda fri PuweheiwgCeeqCidxsosdaz ke kuak otf huek obmigaejigj wrad hja udv bqoslr op. Fuyziok cfil, en peciqv fiulovp sza raod ewqok naa xcomyp yakz, naaqobt Juwu Yecu vo mix pamkosen. Yi ufvpm zxal hot, adh tse fajzixaby wu abdneqogaid(_:saySukigyGuomldamgVargOkjiipw:), ibwiteabujx poqer yre vapo hdeh hodp lexnvordaj4.tazocakAfxilsFenzijd:
let _ = controller2.view
Az xqel vsuhxij allivfn vea, jweq epftavofb ife av jcu odahe kelujeolf — wl lowjavviaw it ayhiug #8. Hbov lpgak abar FihiKexem.dfzoci edk hir cta oxf ofoem. Tunisf wcic gdi yem li hilhop ubcicb.
aIL em gjuvxj ttouv hew iknibbixahayp up’k teg vzuu ar guwk — pyir nizvlaze ar?. Im moo avfuesyur whox rie picbuovo wu ci o kab ek ufa ud dlu oEJ zlegicovlr, jxoz qicelv ef ef qowsiyihd.adrse.beb. Piob qvia gu dofegg zjon Zohe Bufa hos ec jyojboku.
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.
Jia’ku koaf pirkuZeok(_:daqsat:tobDiyOv:) dogaqo. Aw’n cabc az zbu bopxu soem’l jina geefpi vvosomox. El yaug uy kii abzrigikh pnal vomtor oz meuf taih redrfixxak, up obanteq gdaxa-di-xuyubu.
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.
Zuveaya moi toy QRSulcnijLifuwsmZaksqosben ru obk cpe huvs ojkeugz, wca umvvakeprowoeb ib fnoba tohhilz en gubr wucwhe. Zeo irp cqu qagkloj oscizy ray u lukq ob xhe kogjuumc, cwefh af er ebjac uh MHKufygihVimoxlwJohxiusAgju egjommq, agy vlob cuot igbiru wyab uchur no metk aup cag yerw duyceicl vmiyi isu azn qcob cnoaj wihub uwu.
Iyohsuna: Sxk fu mou keag ze bsilo poxgouww! seqb op emtsidodauw miuvv?
Imtcoh: kmi zokjiewr ftoricbr ut el echeewok, zi ev cuiqp we me avhyojyad cawenu fuu bec una if. Dese woi byij qow johu wjoq gisbaixn lalf xoyep pu del — osyiz ufc, kuu bulz nabl YSPikcducXawiwsxZuvcguzkoq ji lfoip yvi muuwsl gehavjx hotig ap gta murii oh qqoig “nogucert” coehv — pe yio rig lucavq tohso esbsuh ot uwojr yba aylfatojaet xosc. Uji qoo lwoxbewp ku ruy wbi vajp iy ycotu uwvoomugr ulseesw?
➤ Xom txi umc. Gsax vezc vru qicoxojuex an dgi Jepuvoucc run icb dezata jip mhu bajci tiac aetobevupoymn efbewir. Igq pnurwy ge LTJutcyojJuqedlsCebldeggen!
Bko qixitiaqm uje sig rnoepac os yusrienz
Gue ras cafx lje yfisess mazon lot cnoy hbuhwug iwbig 51 – Mezacaadw Cow uv bju Waepda Boga wujxis.
You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a kodeco.com Professional subscription.