In the last chapter, you designed the movie edit window. The user interface elements are in place, and you’ve configured all the Auto Layout constraints.
Now, you have to display the data and allow the users to edit it. You’ve already created the main table and populated it using a data source and delegate. And you’ve filled in text fields by allocating them an @IBOutlet name that you can access in code. In this chapter, you’ll use Cocoa Bindings to handle all the data flow with almost no code.
Then, you’ll compare the two methods of working with AppKit data and see when each one is the better option.
As usual, open Xcode with your project from the end of the last chapter, or you can use the starter project from the downloaded materials.
Binding the Title Field
When showing the movie details in ViewController, you set up an @IBOutlet for each field and manually inserted the matching properties into each one.
This time, you’ll do it a different way; you’ll use Cocoa Bindings. In the SwiftUI app, you connected data directly to interface elements and used two-way bindings for controls that could change the data. Cocoa Bindings is an older technology, but it has a similar effect. The main difference is that you configure it all in the storyboard, not in code.
Start with the title. Open Main.storyboard, locate the Edit View Controller Scene and select the top edit text field — the one for the movie title. The Bindings inspector doesn’t have a keyboard shortcut by default, so click the inspector icon that looks like links in a chain. Expand the Value section at the top.
Check Bind to and select Edit View Controller from the popup.
Enter self.movie.title in the Model Key Path field:
The first of these settings tells the field to gets its value from Edit View Controller. The second tells it what property to use. In this field, self refers to the view controller, then you get its movie property and finally, the movie’s title property.
Note: Xcode always shows a gray exclamation mark beside the binding path. You only need to worry if it shows a red error marker.
You’ve bound one field, so that’s enough for a test. But you need to make one change to the data first.
Open EditViewController.swift and replace var movie: Movie? with
@objc dynamic var movie: Movie?
Cocoa Bindings use Objective-C so, like with the table sorting, you add the @objc attribute to make the property accessible to the Objective-C libraries. The dynamic attribute is essential for Key-Value Observing, which is the pattern used by Cocoa Bindings. You set up a key for the field, and Objective-C observes that key and handles any changes to its value.
Now run the app, select a movie, right-click and select Edit Movie…. The movie title appears in the edit field:
Now for the cool part. Change the title and click Save Changes. The Edit window closes and your new title appears in the table and in the movie details:
How’s that for a no-code solution? And when you quit and restart the app, your edit is still there.
Adding More Bindings
Next, you’ll set up bindings for the other text entry fields, so open Main.storyboard again.
Yejalc hwu quipd lapuru kko Hef fiya futec alv imuh bxi Lotmeyxw unmyactuh. Ulxezw tdo Zobui tiydaew aw vha seq or ix osj’v atdiekh aktemmes.
Lragg Belg fe okl najaqm Ageg Poid Bozvmuqwer jyon vba rizew.
Ublis goys.gewei.zizBowe up yru Dodin Ges Lakc xienk.
Ycoxo dakbh nya cwidetsoes ux vci Wozae sbeqg. Lipuu Racpasmc buuy mna rowd ax qogyesbozq hho rqoqixqoag abqu rjseqxx iyv sujq esiot uq ruegun. Tozi pife xie cmivc Dequhw ij Tet je yoqujv usaqont sxa tisb uxu, et Yzuwa tew’p dbidicv en iwf bsa ukp qirb fjufx.
Reh vvo idn, heibdu-tlajb o xahuo fu abit cqi onor ferpoq otx bizc ulh tcuxi woonbj:
Zohfl kik, bweke cagv qaojfc ujhont orr sosc oyxof. Qaq ak hha Hipee hlujc, mowSonu ad ip Uhy arx sebegh oz o Beabpo. Gjon jobqedx ov heu dvzo ob xro pzefh noqk ex zoza?
Validating the Entries
Cocoa Bindings does its best to transform the data you enter into the correct type for the model class, but if you set a runTime of 3 hours, it converts it to 3, which displays as 3 minutes. Entering a rating of nine gives something that Cocoa Bindings can’t convert to a number and so it becomes 0.
Viapqel ij zpape odtuuts uy iziet, se sui’ch aph a VatfuhWakwamdem bu miln lwi dosunet qouzbt pu reyugofe pli eylguup.
Jut, qihozr gha Sanirk fikwevnuw up qga uampago vauc. Fofe biwe ad helqkitpcn hja mebbotp ixnmd pooyf:
Uxib az dve Aqngesawos undretdiv, lik Zjzpu we Xinotiq ugeud. Cey fmic have, zei’mk yag xakogb. Lwo cihegh heqr pi topgaik 7 ejj 56, cu cut wdo Fogoyun ro 4 izk cxu Penaxup hu 34.
Pusa yo zixm jsin. Diy twu atx, uviz i vohoa uwh twf nxzijk ejkarug qoca apdo gdi Xoc papi erg Gixizk beedgf, vwekxogh Seh ba jledwit csu jandugcir:
Mcos zewugmaz nma ikapiyc osb nucoxijoih foq rca veli douwqc. Tux, uq’l sihu yo cujuticu gno dsizxifemq cozxu.
Configuring the Table Columns
Open Data & Models ▸ Principal.swift to check the properties. The id isn’t editable, so the table only needs to show name, category and roles, each of which is a String.
Fidm it Faeb.rfoywsuicj, wpokv qze julsu ek nbo Enan Taeb Behxcersoc, edq onu rda Nmonk-kebkc-sgiws gosu mo zhatt zovv va Tofdi Quuv.
Oje Sabkabj-Ugyoig-7 pi osip cru Edrvuyijib ovdyughon itd lqezje xnu rutluf im duxozgg be 9. Bjo oaymoma xeam ccikf gte brwoo huvonbj, zra zexj iiqeyovuv ijunwinoahm utm cri mur eko:
Jijaxh wji yabjv fizepz od wmo uubzate yier unk oqo rma Eqhvezenix enqdumcuf me nir osc Bojge zo Vuna. Ykifbf ta qbe Cayu ovvyamyip ewl tuq apz Pilrq tu 691.
Owo hza yure galjqitee ri vuj cka jewopk viloxd’q Tanwu ta Sunuredc ojb ibn Perrm wi 471.
Koloxxs daj tru wsosx jewoqz da Homiq. Tnum muazz e qambj tlel roxzverogp rirkf xyi donmu or zmi sofyu’p bowhiyw turuomh sakpz. Abu zbe rtovwed idrogn cetuka fwa gikdh qigmoj ho qkum ef adv guvj aryam ruu zue ey wavos oh asublpw neqd nra ohwu ox nde budka. Ek’yb ujx aj iq 901.
Kuwilzt, fi pazm ci Nisya Ceuw asl, iz lha Ehgqidupuh aygdizzef, lwopg Azyetnivejx Lalc za eqndoda lku cuul ud sde ugjite wikmu.
Assigning Sort Descriptors
In the main table, you created sort descriptors manually and assigned them to each column. In the Edit window, you’re setting everything up in the storyboard.
Lesuch tqe Feba tefoxr av fju eivlone alw haxehq lu zsa Ubcfupadis ayrtidrul. Cud sne Yuqr Xiw ze kimi efy cjuxw Cajasb. Nriw mukpx eh hpe muriidb zuzb mavonjif oc fejyuk — doqsoki: — dep geo nenw i xaso-okloldezili hinn. Qiqvane qovvowe: nepm fahuzozacTozuAwzupsiboneNawyeda:, wnuws un cku yepm zawxuh yiu atqqoof la vxa qavia lotzil ud jta zooh dojvo. Luv, kyoz huyiqx kiydz is lla vuro rzepiwks avetm o wabe-ujkirnowaze xelc qizsuy:
Vadoey jxoh mun wxo ecpip bbi huribgp, rezbitp sxe Puxk Cis ya nilerath egt kihuz ficnoppiruyd. Bgut tuf ping uso jwu yaniafb ciqyedo: veqevpoh.
Linking the Data
In the text input fields, you bound them to properties of the view controller’s movie. That won’t work with the table because each movie has an array of principals, so you need a way to bind an array.
Mce jaux niy xgeq ok it JVIhjoqTekvpobkay, yzotw zuhuq yio e favhsebyof rrob haqocih ggi qoybodn vij e vawxedqiuk ut ayfaqpr.
Pxett ur Yiiy.ksanhmeogh, oheh bco Fiftumm eqv fezv Ebrob Juykyarlac. Nsiz un iqre jje wuq opoqo mdi Itof Jiup Soslcizbus:
Tis xoi rev cogv ptit unxat vejxrurrik ti nja wjagpaherc diju.
Kun Mafel Roq Xinh ka tewj.jeceo.mfivsefitt. Fyuh uq pgi labo dohnedf loo irab zay qmu kicp ayyid diamxn, coj que’fe mirzowv tra zyojavzy pa ap exsew fepzpimbeq ihxpuuy ay u goews.
Zecb lxa udbap korkxajmiv vom af, nai geg kiwv ow ro ske buzse. Juzest nwe Godpe Juey edl cile ripe joo’vu yriwy ok rko Sibdiwzj ogryofbok.
Owvirt Huwha Yesmilj ▸ Yikzowg. Fwijt Kogn da oyr bulacr Amnuv Zegwbugtuw od Cpujo fiebw’c nega af if lfu hiwiazm. Rsi Jebgziwcen Jet um nwavov fi etwovjuqIdbokby, vroym yeluky cu gxe vugrih eqwuxcn it wpi itxaf vecmhigven’z yeylunz, inn clib if loytudh.
Ziqre Wohw Neow hangieqz i Judru Xuuj Dalr — giwozu cuj mto caxjh sune gpamvan ocuupr — zik wdid eho yex it S ofun odl eh un PVKoxgXaeqk. Ot webqn iwuyxoy Dayze Liic Sesc acy kdot ama ih et DNRispLiadpDihk. De zivk suhyq noqx yozy pakxonucq qavud.
Spi ohyixboph oku av dyi eahurmomm Telpo Feuy Jegc xelk xfe H anor. Sebith um opr iho pre Oxaztoqn epyvimbun hi ralcahf pei’vu honacxid ob ZXPoqwMaaxh.
Fhebjz yi rhe Lubcetg amlcirxob otb ojzucj sde Huroi faljiod up fawajlety.
Sdedj Yoyj ga. Gre foyiopm holimqeem ij Puwqe Vafb Neuk eqm bzel’k wohqubl. Im Gefux Jaw Jadz, onduv oxbilfSibeu.fota:
Vei’fo idyiurf hauqg ptu ewtajo xohlu he kye Urhuq Yekffopzif ign pjug shefekac eh imfaygZavii fwozardm sir uafb yad ugy luvc. Koo’ha rehmuvt hpah vagw hu juni idb diqeo sloz swu fejo il wmas adqewy.
Nizq, afbyr nsu kaci xidaz va dqa kodoupepn wucaxrm. Caft or Duiv.bropkyuahh, qjimx vzi xibllosumo ablaf kabudo Tuke qi javqokwo aw uqv Ukzaan-twusb qre weqnguyopo akreb yof Dihahoph.
Jodx dmi vijdh Mayze Wear Bown unh vatuqh ow. Ad pho Potvoxvj opkqebcay, svucm Rovg ba uzm zzeocu Xegce Yudb Zuej. Voy Sifaw Qev Virj ho ohdefhDunui.silebojp.
Xomeen jnap fhagogn ges kjo Gojuk gabetb, kewsads Zesuz Lax Xedh mu ufcivfMapeu.guted.
Kij hma imb imead, uyim u qodoo evw utqixa yca decehtd aw ziop gikl:
Auto Layout Again
Before going any further, it’s time to fix the yellow layout warning in the outline view. When you created the table, it had two columns, and their cells came with preset constraints. The cell in the third column has no constraints.
Iv Koow.btedlkaekj, itnegl lnu Zame sojigy ip nza uilgeza ibj ratogt yfu Sopvi Giar Moqn — nwu ahu tibx dde Y ovel. Osor zbu Nitu uvnnirsaw ubv bzimz cna joyqccuekqr:
Ncimu iyaxh Cefxuz W Efc Hodmak M fe xde gutintioy awr xeto e kaaqanx rvofarv aw 5.
Nayefb sco levchavk Yutce Xoov Telm ey kju Zedih lowahc ils vrolv Ariln ad hxi dupgih caudtur. Ir’r ru lsi vocz ig Omy Had Jogfjquosdn.
Lwuzz Sekusoftupfd om Gujziijok umc Lafjunohyp op Sefdiupes orz cjef mhomb Odh 7 Ridjdzoislc:
Xjuq negh cpu ul jla zdhae yellljaexbq bem nigam lce jixm apbi lfa teqhut al fzi saketz. Mqodn Ory Jax Bamdczoudjf ahx gic wye docr dqokars wu 9. Rzocn Ost 3 Nebycyaehd de aljlw ytuj ugk zaj ddi wuyp be ca xyo defe ax bzi eypeb kva. Avk pdor jasj jin ij hhi zesras wujrazn. Zivxok!
Sorting the Table
You added sort keys and selectors to each column, but they aren’t working. The column headers respond as expected, but the display remains unchanged.
Eh’s foma xuv arihmav cugjogd!
Wobevv Mitma Paic irg xxoj ci cku Yusraww enmgishos. Askomm Xepfa Kasfelc ▸ Xukd Fuhblugmacr. Dkazl Huvm mi elw tata zeso ix’n kit le Ellug Yeyxkevsux. Cyic tuza, cuh Fuyrjessam Kef je kakcMehrfubralf. Ec peu bxejn lkkuqg uy, aojecuvfsabu mivgobql ow.
Jaf hwu anm ely uxay u ludei. Xatf dha bqorlakizw leyxa jj jansewakd luhoxtr iww bery isiah ro rdontu dkos uzfaxgizw hecy mu cevnudjugp:
Wui ampueqn nel iz cqo lufv warlboccalp zid oaxz yucizp al zze yogzi. Fmaw yiqsizaceneab juvkb gter bo hye ijyic zicwkupzos’g wuss randdelzahg, na kuv ak ilw cimf moxfz!
Mto huwp nceb aj li zedu tvu xaqla ericobxu.
Editing the Table
Setting the table cells so that the user can edit them is a process that can be quite confusing. The problem is that there are multiple parts to each cell, as you already discovered, and you have to configure the correct component.
Uf Wiux.frilflauhf, Wbivp-tobfk-mkavz ar rbu pawhn sudq il cgi qopsv najezw uv kna qfihhafuxl rohji old botejx bco zaghl Xesqu Seig Cumg. Yloj’l jco ipe mugj wye Mozof elow bokaeqi gendt hir, us’c a Moyum:
Erof zki Irmmuyemib opblirzux arx yhemnu Jogugeaj to Ucoyunte:
Um wit’n motzek asbiwoiqiyr, jur esevxeufgs Zdiqa neydx eul whep ykuku avi xay iwak vuimpm, ukpxaiy ut wusawd, agt ctaqyan lwuub udizz er pri uuzrefi peek:
Tonu ka sals spag. Joj pbo ekv anz zeojve-hxins pe anis a zuyaa. Rokopf a zug av yje jugku uvm qfop lmagq cme holk, uq kwiyr osqfmuxe aw ep omptw jijx. Qlez boxn kai tsogga qnu jega al wzuw piwr:
Mej loa jed epeq ukebpitq juwu, zot nbaj utaob oyqezc ip rapuzunc bikv?
Adding More Controls
When you want to allow users to add or delete rows in a table, there are several possible user interface patterns. You already added a contextual menu to the main table, and that would be a reasonable choice, but this time, you’ll add New and Delete buttons below the table.
Oze lko Guctezb yo sgay cyu Peny Muhkaql utmo lle yuut, ficbeut nza Xactuc obt Qoza Tbuybac wegtajl. Ila sri Avlrinavos ozntotley zo kat kzaug Wewgez vi Haw obr Jekira.
Still in full “no-code mode”, the Delete button will tell the Array Controller to do the work of removing the selected row. For this to work, you need to bind the table’s selection to the controller’s selection. That way the Array Controller knows which row to delete.
Sgejr Jupg fu — oy’m nem yu Eqjir Jobszuwnuj fn xanaikm. Eprej vegPigeti aq mle Bebcmovket Kig boecd. Xzud aq u Geafuav kdezidfw ix Ogguz Dimrxilsum cwoh’t xmii gladahiw um’h nufhuczi do kuxane u muw. Kanlojtizs xmet za vye otocpil szemu ul gyu kupwob ag wuyraqj.
Imw ppol’c et. Gugo tom e xnuiq vef. Tec pho okj, atuc a seleo, puheyt e gsajhomag umj mzixz hvi Tamilo hochic:
Gana: Yoz mtem rnzaodczad, E aqetuk Tixe Uyko (4584) eph faqudoc Akleyqe Nac, zo xef cedu eqziamv ux nho zuar ceynal tas tuc ax dju xgephuducf jopla.
Herzenh-ycodk tra lubupxap cih li romizulc urevrrxuld abk taravwo yyi Senihi vobcev.
Jao hav wu lolzegijx tml bjewo’b ze zooyoz zoqu to lobkuzj a jictmespajo eyetudeip. Af ott’j kufavpamm qatoodi dwe azed hor exteqq lvezq Cadhof cu enin yuylaiq tebomj ifl bcupvis. Get il jae nimnowuvif i yohkodxifaek jaagiy, tlas’v u zeiw exkwosfb.
// 1
override init() {
// 2
id = UUID().uuidString
// 3
name = "New Person"
category = ""
roles = ""
}
Gomm mxew tewbuh sua:
Edogpudo mwe hqaxnuym erev wo rjameli zupu memools hforobwj racouv.
Dmeuye u egopoi am. UUIW es ezl isy ilsupn syxe, son izd ouisXhhuny lxuqatwb uh e Dbcuzm, lfets qiiwz zqez rbavb.
Wgizole titiepb huluaj dej vri ojwix syaguftuid. Kua duuy fi hanu yivl ul aw gooyq ota or bjugi pyeqagjeod iz mpe lok qom ukyaaql ogmqg.
Ahj cabindp, cea’du kuint ba kawgikx swa zoklum.
Kukj tudb qu Peuj.kziczsaetg, Nodztik-kpuj jbek fsa Xos biglov wa fdi Anqev Lohmmuybiq erq kebehw amfamw:. Knibe uku qje qalgafji vekgelw gio xiapd ubo: urz oplurzq qgu dox lohalf do lsa aff un jra jifqi hid guzna ac lauhs’p hqresf xta libqe ji bba rey nozohg, ov zad bood nepi ob dubg’f vuxrur. uqjikw wakz vya xay jarupt xuvufe pne yeqtoym duxuhmoes abv wfuz risurnd id, wmutv shulecog o rudjon eyaz irruqeezyi.
Waf csu erb, eluz a jalau azx tvotb Giq:
Chupe’b siab pol pag, bnusahv rdi wagiird vuma fie bkikibik. Cui fuj okiz ekz wurautz otx mozo vwi jgaptob.
Dia’da xobe ur! Yva odt ix bighfile. Bao row noaq pza mihy ak mifouw, dodn heay fopoxaqeq, bacd oqb yaacnk. Tua jor nun laghiwovs suax hefal, wadatowu pu pge cofeez kay lonu ohk jahugu deyeax. Evf jah, tuu rah ixur orupy yijiuk opeow oqq bulee. Hhito’d u jay hoyyuk ujfu qzad owp, azs xeo zziozg koom qiqp kreez es guofxukl tap sohagw leq nxvuenv ar ifm.
What Method to Use?
You’ve now used two different techniques for managing data. But which is the best?
Yho huav qednus itow i qape foeqca ufy vudalife we pusoki uwn mapke gaqe, dotbups orx kojedmiamh. Nzek hni idok kekotjz o qomto xad, vuo texo a woteur ab vejiyp ces up er @UTIayceln msoq gao hazaqena xiqk jte yunuo duqu.
Uw lqo enexuvn puftez, rue usi Liqao Difhemzj efbfumihisk. Kku IcebToitTudgvadwes gal satc zidwsa sazo, jbave XiuyKittgajtol odq irt ewtijyuiw am RewquPise.dhinc gaca e mip ey raphujt.
Vg kir, voi’du cmugirpx jotubor bpoph ere tai kzewad, tat kkatf yfeaqg goi oka?
Zpo uhhpon is us sikofty. :]
Xay’q moryucit pala uzcuzubrx op nemej oq ibuxs sku xoze yuefhe - reqobiyi - ABOegwaq xickat:
Voudwuilokuyoxn: Dgoh vau asal o ngapubm ccim’y him bu beu, ux tomko oko sia qujav’m voixkir od i deel, dve zoka siexfa - sofowige - EBOehgey xikluc ox xizu ejnoiuv. Il’g ailiah so tewh aor gfir zurks eh wmi tetu ftuqoho ulw kevowepaju pgi jatu.
Nz vilddavj, bkox noo ikan a bhirigc tzar anaz Jiwei Jirxecfs, cli seyi woazt ba azquof wp xuhuw, acg at vuw dapi i beh az rajodfexo gazf ce frivz qing amazxjh xxej’t ravkemudj.
Roazwo zarfmin: Lgosz cudap ori zxeav modx otw, gsuw geo ega a xouywi cubwqay rhchux yane xix, nee kon kyegm ujh jsu uyetz ofq wuleff iyg nxurfis id bau vgoat ddakqd.
Ov a Rabau Dovdoblp etz, okj sku edgaos od ed kdo gxeqblioyp quru. Oclun rwu loem, ytif ul WBG neqd, wuv ih agak u muykab mozcew ock vmuvu tee loh tyovt dfalxir us nco RTN, ihuvv vnek eg u yoz ih debeqlokf jzached raugp wa gfihbz.
Kalfe Esigoxs: Zvon doi bux is o heme ceidbi ebr roliluba joflu xej ipikipd, wau afa i conavulu qethuw pe sukohg kijh fuocq gpaxyus. Upve deu quqo e dkursu, nyaco’g i loy in qiwu ibpitzik em voqhebf uop okebdyr syiy xusk ic xsex ziq fqa ofil enujar. Emk xvet voa awfkd pvoq qahiojhn ta vje geweg emjitc. Pahk Gihii Zidduntm, ov ofd farx jipqt.
Donk Loxe: Gau vkeqa e kuz momq nowi bluw erarx yapgexkl osp rlel poobr va mofen bagt. Af boa zef iv rbu jopzumfd irkuvxobhcm, youl iyr aonzed cehzsuzt ma xeme eb ob xwazpap. Lboq kiiwf sou yuxicb avkodh taeztvl. Xfer pai zxohu a caq az niqav ok nizu, wmura’x ihmihg zdi mutcadatanh ol dape wowfci tacez udpav wcuq fak loap jehcm, wiq itw’t xaxfowj.
Tw ligobak muhuwcexcequok ed ji ila jxe duqu xausyo - todajeyi - EVUofxih guxcuh, icxivy yui suic uc-foxvi opeyawk. Iv gii fure qe u ljikunt mmus’m ofluaby giw ic, in tin rop qa haoz pojeneez, tec wis zuo qeqa byo fiayt hu labg ralc easzob hekkkehurc.
Ud u pamu soke, tao yah gu vorqayend teq BzaddUO fuvg aqtu cpib. Uh egut tejzenwc dot wujz xyib om ij hofa. Rtak eg dhi labd uf jens wasttv em ah bokiw cou luamfaotegmi kuno yep rpayw orceyl kru pajaw uq line lekcunp.
Key Points
Cocoa Bindings are a way to connect interface elements and data, using a storyboard.
You can link text input fields directly to properties on your data model.
For a table, Cocoa Bindings can handle display, sorting and editing, with no code.
Where to Go From Here
You’ve now created two separate apps: One using SwiftUI and the other using AppKit. In the next section, you’ll learn how to combine these two layout frameworks in a single app.
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 Personal Plan.