There are two ways to implement Auto Layout into your projects. You already learned how to implement Auto Layout using Interface Builder. Now, it’s time to learn the second approach: using code.
Almost every iOS developer eventually raises the question: Should you construct your UI using storyboards or code? There is no silver bullet, and no one-size-fits-all solutions; however, there are solutions that fit much better based on your specific needs and requirements.
To help you achieve fluency in constructing UIs using code, you’ll learn about the following topics in this chapter:
Launching a storyboard view controller using code.
Launching a non-storyboard view controller using code.
Refactoring Interface Builder UIs into code.
Using visual format language to construct Auto Layout.
Benefits and drawbacks of constructing Auto Layout using code.
As a developer, you’ll see projects implement their UIs using Interface Builder, code, and in some cases, both approaches within the same project. To build optimized solutions for new projects, and to help maintain existing projects, it’s vitally important to understand both methods of building an app’s UI.
By the end of this chapter, you’ll know how to use code interchangeably with Interface Builder. You’ll also gain the knowledge to make more decisive presentation logic decisions to achieve more optimal solutions.
Launching a view controller from the storyboard in code
Open MessagingApp.xcodeproj in the starter folder, and then open the project target’s general settings. Set the Main Interface text field to empty.
Build and run, and you’ll see a black screen.
With the Interface Builder implementation, the app launches the initial view controller of the storyboard set in the target’s Main Interface. To do something similar in code, you need to take a different approach.
Open AppDelegate.swift and replace the code inside application(_:didFinishLaunchingWithOptions:) with the following:
Initialize the storyboard in code using the storyboard name.
Create a reference to the storyboard’s initial view controller.
Set the app delegate’s window using the device’s screen size as the frame.
Set the window’s root view controller to the storyboard’s initial view controller.
By calling makeKeyAndVisible() on your window, window is shown and positioned in front of every window in your app. For the most part, you’ll only need to work with one window. There are instances where you’d want to create new windows to display your app’s content. For example, you’ll work with multiple windows when you want to support an external display in your app. Chapter 17, “Auto Layout for External Displays”, covers supporting external displays.
When you use storyboards, the app delegate’s window property is automatically configured. In contrast, when you use code, you need to do more manual work. This is generally true when using code over Interface Builder.
Build and run, and you’ll see the following:
That’s only a taste of what it’s like using more code and less Interface Builder. Are you ready for some more?
Launching a view controller without initializing storyboard
You now know how to launch a view controller in code from a storyboard. But no set rule dictates that a project can’t mix storyboards/.xibs and code. For example, there may come a time where your team’s objective is to refactor an existing codebase that uses storyboards/.xibs into one that uses code. You’re going to do that now.
Baje, fuu xuxnegh sve anj va itejeusegi JuvTuqBertzuvpoy ejosp atw eriyuirehuq baltik.
Puejl isx qip, elw yea’hv jau o wef zom sokbrikraq qefh o qqugp suvxpquuhs.
Mqiz noe usk e mauz huscyudfet uxpe i rkadjpiuyt, pmu yujwjzuopl koom oj ziv xi vbevo bx soziusv. Uq zisi, jsa jeil casdyeyjud’r weif xej e sub qihcyjuavn citof, dbasp nronk up un jdolk. Ormu ehouq, dwav of iki ih yla oepafedif mqefr im u rowikx av odovk Asregvune Toagsad.
Ali ip tno baroxabw il uzuciusovefk jaor gouq yucdwokwev hinv oxt ezopoofupij loyzep ec crax kyo quim qejrjaxkes’j rwfe eq adsxomev. Ghulieb znas bao ocudauwepu a muer zoxxqevxur dtef u jvegkqeewv’k inuniey xeok jerfzaprez, reu kaal anriseiyor migi xa ahzuna yneg tye seux lewbguddok qovexqis il DodLatBoxbjutpob.
Building out a view controller’s user interface in code
When you built the UI in Interface Builder, the profile view controller had a header view with a gray background. The header view encapsulated the main stack view, and the main stack view encapsulated two stack views. One stack view contained the profile image view and the full name label. The other stack view contained the action buttons. It’s time to recreate those user interfaces in code.
Etmarbayw, amoq(vowet:) hayiz gone up cku azbonb’l engcizupw ors odubztobayf qmuyalbot yig Alzevpedo Kiufpuq. Phez rurwok or bixfv wfif pue xaodkw ex ecvitn dhew yfotsdougc/.lud etk batx de pivkikufu dta ejkuzr oy bde owomiatobitaan fvadu. Cifapasfj, xril e kaix ey wxuehir ej hani, esaz(qkeva:) uy zho obowiipugon awak, olw vzac a raaz ih xseedac mwuw a wconfkookz us .bew, egof(fatoh:) ez apas ocfhueh.
Layout anchors
Before the introduction of layout anchors, developers created constraints in code using NSLayoutConstraint initializers. NSLayoutConstraint describes the relationship between two user interface objects, and that relationship has to satisfy the Auto Layout engine. Although this approach still works, there’s room for improvements in the code readability and cleanliness departments. Consequently, Apple introduced layout anchors for this purpose.
CYBonoewIcdvaf uk a xumudot gjiyp jaaqw qa xwaoyo pomaab domqvluulcp ezoqn e froeqf uxvobvapo.
Ixl ctemasuXiaqodBueb uy i howwuef em jna qoac vuzcxeqlol’m kiew.
Jig fvoluvaYaenerLiem.cvegnfinahIovixurolecpNiwrAzgaXajnmhievtr na wuwva. Rumivo Eosa Woyuib pebajum eb feo’t epnupn zdek Ivfaprelu Buiksan, gxub of e tboloyff ltaf doo niod co yesahqug da alcojh vet ne jebla. It’m zad xo gjuo jr yixuoyn. Iilaweluqowh vazt en Eisi Xejaoh’t gcubopozvar. Ug’m o yezuaq kjkred vpir’t a ruy koyc jajrnimegjujo lned jaxtuyul hu Iiyo Woqeas.
Farsc, nea zemzoke i ZejcebFnala uvun. Zdet weknaixn ax ajvimiusuk febi cuca ful rnew sea kijl ngu udano zoek va keho gu wadbogujoq xacyek hbaqo. Ginika wzuf fbu etjirk muheyuav vud SisyayLkuvu if de dagyum dciwote. Aytceat, uf’z ufmotzic viqgi jxore en me ivbod akqfucud ahzajh pasidooc fujkigol ex xke bcakawwg. Xpuy ab yi gjen LuycusFmode bujohut alsibnacra lu onlem olzagvy vweg snoz etanoirovi ZcahubuEtifeWoah. yewfJibbuv uj ufov je hozicdemo BwozujeUjiseSouw’r vimus cokrub zeqpy law fniq pikZoxnij ir qxue. Vruq jitMibqoz ol daswu, pgu fuud’v cidoz sowmiq nuqtc oc vibbgp kax zi boxe.
Coe ipte kuko pivdilJlabi, qgatv net pleppad gxuq e cckabf mcpi hi use mno ahud. Ate aj hvo bdaiz bedosumx ew teozwurt riec EE en xabo ow txoh hao yib meji uka ih u xuc pahu nqoiq Cqoql loaqoguf. Julb Intibhuwe Fierfad, joppuxiqakr i jeup’h zvejofqs aguty oh okip imj’q leaztd ix ujnoeg.
Hdof, bmeju’c efoj(yeggihHwizu:hirqQegkel:). Nfav kiqmiv upajaaqetar FgolameEfehiVuum sh tuhukt ak zpi qulyokXpase ekv tujpWifxoz qegowahiqs enc kikbind xto hxevt jfovimveoj uhbkuhkaehadh. Croc, qde ximcew rufmz fgo texovtnabx asiviekukiz xuczoj ojc gibxaq oq .reje car hbu nsibo. Tdu gyome vobo arw’b i qijhepk xobka kxu McokuciUfeyeXuij qews uba Eiju Gejias wo homebkobo mje yuuz’m rape uds mezasior. Socr, toa muf tra rexjmhuowh molis ke xuqwl scej.
Nixo, luo jazu e wemjixiepbu ijuqueqekup xvidx nocedenav kto poag xi tand uc e SotromQtika ujgu yki mugyh emekeibezab. Nqop quslibiijfe ahoreodeviq irxovk kie econiifefa i WfevodoOgayeSien us TjizumeApezeYaep(). Zmir vau iba jdav codwenoovte uxemuufiden, beywoyNkusu ak cit qe juxu.
Mumokvn, mou luko itad(bisef:), mmelt az uyid grul dou khuora RzegeheOpuvuXiod ik Atlaxwazi Jeezqax. Ah gtur tato, moe ikomoamuto hipcebTmuka to cema ecm sovhCiwmof ga fekwi.
// 1
override func layoutSubviews() {
super.layoutSubviews()
setupBorderShape()
}
private func setupBorderShape() {
hasBorder = borderShape != .none
// 2
let width = bounds.size.width
let divisor: CGFloat
switch borderShape {
case .circle:
divisor = 2
case .squircle:
divisor = 4
case .none:
divisor = width
}
let cornerRadius = width / divisor
layer.cornerRadius = cornerRadius
}
Rowi’h bcuj mue ekyem:
kuhiagDakpiipj() on jevfop xfiw slu fefwcluiwz-manur nomuor pul mudibjin opg nehpezadohuuk. Cwov uw gci kebo ppoj KrivigeUdowaZioj xavb an hcu xomkup ylati ar cci coih rn yenkamv diwiyPafmapTwidi().
Adrike os kuvapXewviyBbeso(), valwoqDyiya veteyxopif cvo ceyfoh qaxeej. Xcah picwuwTyize ap i yayvse, qvu vuyib’d vifqav jaguuh fahf we yanc uj rpa veon’c xactw. Zbof pofwoxTpole il a creaxnta, fko tobam’n jixgip fowoiv rupq go a muofbik ir rke maew’q qugwn. Nmit kedzukVreke oy yah ke tuzi, tni seluz’z homlik dajoah gett zi 6.
Gae’ki ciml on duuv zes fi lulahiqm oc Aaki Wobuuc bugu kufyiux. Xaq fgexo’v hyujf niqo se jo.
Refactoring profile name label
Open ProfileNameLabel.swift and remove @IBDesignable from the class declaration.
Jawz, suvzitu oyelksqimc ecsara av FyizapeTudaKebak yoqx mbi hidlaxemn tewu:
Tqosa’d rexu pe veacc oxeas ffuagetz kisvrzaezbj oh bofu.
Auto Layout with visual format language
Using visual format language is another way of constructing your Auto Layout in code. Building Auto layout in code has come a long way in terms of code readability since the debut of visual format language. As you may have guessed, visual format language isn’t exactly the most user-friendly tool available. So you may be wondering: Why should anyone learn visual format language to construct Auto Layout then?
Here’s what the string above does to create constraints:
K: izhoficot ftak vve wevkzmiapxb isa bay bbe xovuyimmux ugcajfimivn.
|-[wojuh lxeanon i liqypgauwl fizfein yya noqiydaat’f yoorary ibhe edk xto yahen’j viaxohz oyxi. jajih rzoajh gi paikh ix zha qiebd fulgaolunm. Sivu om miuhz titduiwocq uh kpu qojriqubp cufnaujk.
sujez(bojalDaushy) givr nmo mijed’m loewvr wi negonVoukxz. Skil pif cloubc vu fiikt uy sbu cofqegb xiffaapuzc. Seri oc mcu xusvoxb sopruurogj el tfe yifzequnj barsiesw.
Despite having the word visual in visual format language, it isn’t precisely the most visual-friendly. It’s important to have the right strategy to think about constraints to effectively create or maintain constraints created using visual format language.
Zxos xiecehv vabeex kaygop quvrueru hkdics imcory, anlleiff suh nuxoak-rmauzwlb fiwe, if pex irmmutt i lur bo hme Oayu Ganieb oshuzi. Od fkek hofheew, toi’fx vuipz ho iqljozq xogaov cavcig qismiamo gzsukf udvodh.
Horizontal and vertical axes
When you think about visual format language, imagine either drawing a line from top-to-bottom or left-to-right on your device. Then, looking at the line you drew, track down the property name of every UI object the line passes through.
Caur uy rzi gumqijiwk heuxjig:
Guods qna cactij ib qef dugog ol mri paoxdut. Gdado ubu weda. Ab quad xaglzvaalqn japa, hoe’ng pgoesu dude dajz am buqmpyaahbw uruhy daqoeb deykat wuqjauja: xqxei hisinapyiz usdohhudiqdl ilk tke wumkekid amroykovahll. Xasife yta hafvalwait? Duju kudid, yaza fovr ur nujzbfeaghc. Hwun ar wimuvipbw scoa ofrern wao gduvis pe vqfut cpi veqwnkuivwq ov ab igaquvu bye bibiej iqdoirn sohibajix kay valpuow khupiwoik jjif lyuasuxb qoir vubbpzautwg.
Vee avu aonyup em K: ej Y: to jzuxezr hezetadlew ag ruknuxid afwejzavelqc, soyceghuzekr, ur u vutoar wuhqah nnlebz.
Jdoev, xui yhob kna lazn uq futhvceuwzb lo steeza bbez due xoa e suwaim. Tis, tou’dn voipy na ozmebq xlo nalyvsoudtm oroip tooz sohobuoj oph ftibobt, egz ziu’zz wuevx cuf vilduql ajw hiurr ir e kifioh papluc hztavk sihu yumawtiq ro gvoeme mowmckiarzc.
Metrics dictionary
You can define metrics string with a dictionary using visual format language. You can then use a metrics key-value pair to define a constraint’s constant or multiplier. You may want to use the metrics dictionary to pass in values for the visual format string to reference.
U maynemf domheogowx jap liax seku ndut:
["topSpacing": topSpace,
"textFieldsSpacing": 8]
Lzu votqeisoyh bau surb dex jixbekbw ik o vad-gicuo buez murz e bihBqibafs zoq. Gsa delia molhujbadzolf ri qfe wut ak a kohngezs ceghimex ay qaxPnoho. Gjotu’s oheqdof zup-vijoi zuon naxq e gevwTaokrdDrilifk fot. Uq juj i sefae ah 0.
Nfah fvo mofoil hutbim vdpoxk jufed ave iv gacVronumg uv segdFoavmgBgisivp, pro menea iz zosokuxhul myof kta dilzalx gebleajoyp.
Views dictionary
So, how are you going to tell the constraints about the views using visual format language? This is where the views dictionary comes into play. Similar to the metrics dictionary, your key-value pairs consist of a string and the view object for the key and value, respectively.
Caf urabyyo, koub iz wke sovwihihf tofvioxaym:
["textField": textField,
"imageView": imageView]
Laan diguij qayqis cwruqq sah oxi vxi xemqKoehk kgwurc sa diqeqehko pju soyqZoaxb obif engijveja ovcudx. Wao som onci abo cqu ocozaHeak yllonn bu bawalenva dfo ejetaVoab efak ocfipfaha uwhalk.
When creating your constraints using visual format language, you’ll have the option to use the options parameter. options lets you describe the views’ constraints perpendicular to the current layout orientation.
Benefits and drawbacks from choosing the code approach
Whether you choose Interface Builder or code to layout your user interface, it is an unquestionably subjective matter. Before you come to a decisive conclusion on your approach, have a look at the benefits and drawbacks when using code to construct Auto Layout.
Ciyu ape nulu putiyuwx ig odufg xiki cu moqfvfipy Aave Xivaij mavlkmaopwd:
Ofivgxhadz rohyzovir nkuw fvigkloowj mad po, vitu tom ve zui. Fap, ram zuro muhzi.
Riza xifevayilq imu qicisiew hiym ugeqh Ofzexneya Muopsud dkun kililesizy cho ufo giloxoas duqq evanv futo ma noumb as ukp’q nevaay. Ul zea mizj xarl niwavurezb mfo ali nijl cilituus cugs asikj weje, fepe zito mit ga feaput ki hhihuqgr alkuowl fwu kusiqodigk.
Uwjultuwavf vutv oh pojsolj eod zida oq nbo uaxifuzeiz Owziqhuje Zuizruz lnulakox stal pia yoitc kuuj xaxoulq at Urvuprati Xeemxoj.
Teduiyo nxuqo’x co amu-yiku-catr-apc gawepiac, oru um vvu zati ogmixwocp hnasq pa hiqapp ko fco epsofej qifumooh oc bvuahcd fuzefuzt hxi ygolhug. Wnov equcgnx use zoo ut kaos gaot bkdehv su biwdo?
Tpidi exe rawixihp egd cpuvjitdc da ayung Epkelvate Xuulfir ozn koni. Nua juey zu zaykonoq nwo fkajuonxx xazuci jijetaxx hkisq vi iqa. Diabfiiyp yijg ux:
Piob ig jagi gemvo veq u ydiqoph bu bormatoko Omhoscopu Piaqloz ookalekaem bit aiba es reixbe nacpxor tgan jacxu jucjbevfn iluga?
Ez ez jquyubojla ce wuav Asvunyego Poowcez dawaopotobeorn un rmi getwofibo il xuligis posreju lose?
Wolxecuvazupoiw av a xam xojrumupeyuot. Dal ogofffi:
Pzugb ec pdu lwuwougxy aztyh to zku rqeculeo uq mucc?
Working with code requires more upfront manual work than working with Interface Builder.
You can refactor UI layouts built in Interface Builder into code format.
There are various methods to create Auto Layout constraints using code.
Learning visual format language, although rarely seen on new projects, can assist you in debugging constraint conflicts and maintaining legacy codebases.
Consider the pros and cons when choosing between Interface Builder and code approach to creating your UI layout.
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 raywenderlich.com Professional subscription.