Tải bản đầy đủ (.pdf) (371 trang)

Ebook IOS programming The big nerd ranch guide (5th edition) Part 2

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (13.26 MB, 371 trang )

11
SubclassingUITableViewCell
AUITableViewdisplaysalistofUITableViewCellobjects.Formanyapplications,
thebasiccellwithitstextLabel,detailTextLabel,andimageViewis
sufficient.However,whenyouneedacellwithmoredetailoradifferentlayout,you
subclassUITableViewCell.
Inthischapter,youwillcreateasubclassofUITableViewCellnamedItemCell
thatwilldisplayIteminstancesmoreeffectively.Eachofthesecellswillshowan
Item’sname,itsvalueindollars,anditsserialnumber(Figure11.1).
Figure11.1Homepwnerwithsubclassedtableviewcells

YoucustomizetheappearanceofUITableViewCellsubclassesbyaddingsubviewsto
itscontentView.AddingsubviewstothecontentViewinsteadofdirectlytothecell
itselfisimportantbecausethecellwillresizeitscontentViewatcertaintimes.For
example,whenatableviewenterseditingmode,thecontentViewresizesitselfto
makeroomfortheeditingcontrols(Figure11.2).Ifyouaddedsubviewsdirectlytothe
UITableViewCell,theseeditingcontrolswouldobscurethesubviews.Thecellcannot
adjustitssizewhenenteringeditmode(itmustremainthewidthofthetableview),but
thecontentViewcanresize,anditdoes.


Figure11.2Tableviewcelllayoutinstandardandeditingmode


CreatingItemCell
CreateanewSwiftfilenamedItemCell.InItemCell.swift,defineItemCellas
aUITableViewCellsubclass.
i​m​p​o​r​t​​F​o​u​n​d​a​t​i​o​n​
i​m​p​o​r​t​​U​I​K​i​t​
c​l​a​s​s​​I​t​e​m​C​e​l​l​:​​U​I​T​a​b​l​e​V​i​e​w​C​e​l​l​​{​
}​



TheeasiestwaytoconfigureaUITableViewCellsubclassisthroughastoryboard.In
Chapter9,yousawthatstoryboardsfortableviewcontrollershaveaPrototypeCellssection.
ThisiswhereyouwilllayoutthecontentfortheItemCell.
OpenMain.storyboardandselecttheUITableViewCellinthedocumentoutline.Open
itsattributesinspector,changetheStyletoCustom,andchangetheIdentifiertoItemCell.
Nowopenitsidentityinspector(the tab).IntheClassfield,enterItemCell
(Figure11.3).
Figure11.3Changingthecellclass

Changetheheightoftheprototypecelltobeabout65pointstall.Youcanchangeiteither
onthecanvasorbyselectingthetableviewcellandchangingtheRowHeightfromitssize
inspector.
AnItemCellwilldisplaythreetextelements,sodragthreeUILabelobjectsontothe
cell.ConfigurethemasshowninFigure11.4.Makethetextofthebottomlabelaslightly
smallerfontinalightshadeofgray.
Figure11.4ItemCell’slayout

Addconstraintstothesethreelabelsasfollows.
1. Selectthetop-leftlabelandopentheAutoLayoutPinmenu.Selectthetopand
leftstrutandthenclickAdd2Constraints.


2. Youwantthebottom-leftlabeltoalwaysbealignedwiththetop-leftlabel.
Control-dragfromthebottom-leftlabeltothetop-leftlabelandselectLeading.
3. Withthebottom-leftlabelstillselected,openthePinmenu,selectthebottom
strut,andthenclickAdd1Constraint.
4. SelecttherightlabelandControl-dragfromthislabeltoitssuperviewonitsright
side.SelectbothTrailingSpacetoContainerMarginandCenterVerticallyinContainer.
5. Selectthebottom-leftlabelandopenitssizeinspector.FindtheVerticalContent

HuggingPriorityandloweritto250.LowertheVerticalContentCompressionResistance
Priorityto749.YouwilllearnwhattheseAutoLayoutpropertiesdoinChapter12.
6. Yourframesmightbemisplaced,soopentheResolveAutoLayoutIssuesmenuand
updatetheframesforthethreelabels.



ExposingthePropertiesofItemCell
ForItemsViewControllertoconfigurethecontentofanItemCellin
tableView(_:cellForRowAtIndexPath:),thecellmusthavepropertiesthat
exposethethreelabels.Thesepropertieswillbesetthroughoutletconnectionsin
Main.storyboard.
Thenextstep,then,istocreateandconnectoutletsonItemCellforeachofits
subviews.
OpenItemCell.swiftandaddthreepropertiesfortheoutlets.
i​m​p​o​r​t​​U​I​K​i​t​
c​l​a​s​s​​I​t​e​m​C​e​l​l​:​​U​I​T​a​b​l​e​V​i​e​w​C​e​l​l​​{​
​​​​@​I​B​O​u​t​l​e​t​​v​a​r​​n​a​m​e​L​a​b​e​l​:​​U​I​L​a​b​e​l​!​
​​​​@​I​B​O​u​t​l​e​t​​v​a​r​​s​e​r​i​a​l​N​u​m​b​e​r​L​a​b​e​l​:​​U​I​L​a​b​e​l​!​
​​​​@​I​B​O​u​t​l​e​t​​v​a​r​​v​a​l​u​e​L​a​b​e​l​:​​U​I​L​a​b​e​l​!​
}​

YouaregoingtoconnecttheoutletsforthethreeviewstotheItemCell.When
connectingoutletsearlierinthebook,youControl-draggedfromviewcontrollerinthe
storyboardtotheappropriateview.ButtheoutletsforItemCellarenotoutletsona
controller.Theyareoutletsonaview:thecustomUITableViewCellsubclass.
Therefore,toconnecttheoutletsforItemCell,youwillconnectthemtothe
ItemCell.
OpenMain.storyboard.Control-clickontheItemViewCellinthedocumentoutlineand
makethethreeoutletconnectionsshowninFigure11.5.

Figure11.5Connectingtheoutlets



UsingItemCell
Let’sgetyourcustomcellsonscreen.InItemsViewController’s
tableView(_:cellForRowAtIndexPath:)method,youwilldequeuean
instanceofItemCellforeveryrowinthetable.
NowthatyouareusingacustomUITableViewCellsubclass,thetableviewneedsto
knowhowtalleachrowis.Thereareafewwaystoaccomplishthis,butthesimplestway
istosettherowHeightpropertyofthetableviewtoaconstantvalue.Youwillsee
anotherwaylaterinthischapter.
OpenItemsViewController.swiftandupdateviewDidLoad()tosetthe
heightofthetableviewcells.
o​v​e​r​r​i​d​e​​f​u​n​c​​v​i​e​w​D​i​d​L​o​a​d​(​)​​{​
​​​​s​u​p​e​r​.​v​i​e​w​D​i​d​L​o​a​d​(​)​
​​​​/​/​​G​e​t​​t​h​e​​h​e​i​g​h​t​​o​f​​t​h​e​​s​t​a​t​u​s​​b​a​r​
​​​​l​e​t​​s​t​a​t​u​s​B​a​r​H​e​i​g​h​t​​=​​U​I​A​p​p​l​i​c​a​t​i​o​n​.​s​h​a​r​e​d​A​p​p​l​i​c​a​t​i​o​n​(​)​.​s​t​a​t​u​s​B​a​r​F​r​a​m​e​.​h​e​i​g​h​t​
​​​​l​e​t​​i​n​s​e​t​s​​=​​U​I​E​d​g​e​I​n​s​e​t​s​(​t​o​p​:​​s​t​a​t​u​s​B​a​r​H​e​i​g​h​t​,​​l​e​f​t​:​​0​,​​b​o​t​t​o​m​:​​0​,​​r​i​g​h​t​:​​0​)​
​​​​t​a​b​l​e​V​i​e​w​.​c​o​n​t​e​n​t​I​n​s​e​t​​=​​i​n​s​e​t​s​
​​​​t​a​b​l​e​V​i​e​w​.​s​c​r​o​l​l​I​n​d​i​c​a​t​o​r​I​n​s​e​t​s​​=​​i​n​s​e​t​s​
​​​​t​a​b​l​e​V​i​e​w​.​r​o​w​H​e​i​g​h​t​​=​​6​5​
}​

NowthatyouhaveregisteredtheItemCellwiththetableview(usingtheprototype
cellsinthestoryboard),youcanaskthetableviewtodequeueacellwiththeidentifier
“ItemCell.”
InItemsViewController.swift,modify
tableView(_:cellForRowAtIndexPath:).
o​v​e​r​r​i​d​e​​f​u​n​c​​t​a​b​l​e​V​i​e​w​(​t​a​b​l​e​V​i​e​w​:​​U​I​T​a​b​l​e​V​i​e​w​,​

​​​​​​​​c​e​l​l​F​o​r​R​o​w​A​t​I​n​d​e​x​P​a​t​h​​i​n​d​e​x​P​a​t​h​:​​N​S​I​n​d​e​x​P​a​t​h​)​​-​>​​U​I​T​a​b​l​e​V​i​e​w​C​e​l​l​​{​
​​​​/​/​​G​e​t​​a​​n​e​w​​o​r​​r​e​c​y​c​l​e​d​​c​e​l​l​
​​​​l​e​t​​c​e​l​l​​=​​t​a​b​l​e​V​i​e​w​.​d​e​q​u​e​u​e​R​e​u​s​a​b​l​e​C​e​l​l​W​i​t​h​I​d​e​n​t​i​f​i​e​r​(​"​U​I​T​a​b​l​e​V​i​e​w​C​e​l​l​"​,​
​​​​​​​​f​o​r​I​n​d​e​x​P​a​t​h​:​​i​n​d​e​x​P​a​t​h​)​
​​​​l​e​t​​c​e​l​l​​=​​t​a​b​l​e​V​i​e​w​.​d​e​q​u​e​u​e​R​e​u​s​a​b​l​e​C​e​l​l​W​i​t​h​I​d​e​n​t​i​f​i​e​r​(​"​I​t​e​m​C​e​l​l​"​,​
​​​​​​​​f​o​r​I​n​d​e​x​P​a​t​h​:​​i​n​d​e​x​P​a​t​h​)​​a​s​!​​I​t​e​m​C​e​l​l​
​​​​/​/​​S​e​t​​t​h​e​​t​e​x​t​​o​n​​t​h​e​​c​e​l​l​​w​i​t​h​​t​h​e​​d​e​s​c​r​i​p​t​i​o​n​​o​f​​t​h​e​​i​t​e​m​
​​​​/​/​​t​h​a​t​​i​s​​a​t​​t​h​e​​n​t​h​​i​n​d​e​x​​o​f​​i​t​e​m​s​,​​w​h​e​r​e​​n​​=​​r​o​w​​t​h​i​s​​c​e​l​l​
​​​​/​/​​w​i​l​l​​a​p​p​e​a​r​​i​n​​o​n​​t​h​e​​t​a​b​l​e​v​i​e​w​
​​​​l​e​t​​i​t​e​m​​=​​i​t​e​m​S​t​o​r​e​.​a​l​l​I​t​e​m​s​[​i​n​d​e​x​P​a​t​h​.​r​o​w​]​
​​​​c​e​l​l​.​t​e​x​t​L​a​b​e​l​?​.​t​e​x​t​​=​​i​t​e​m​.​n​a​m​e​
​​​​c​e​l​l​.​d​e​t​a​i​l​T​e​x​t​L​a​b​e​l​?​.​t​e​x​t​​=​​"​$​\​(​i​t​e​m​.​v​a​l​u​e​I​n​D​o​l​l​a​r​s​)​"​
​​​​/​/​​C​o​n​f​i​g​u​r​e​​t​h​e​​c​e​l​l​​w​i​t​h​​t​h​e​​I​t​e​m​
​​​​c​e​l​l​.​n​a​m​e​L​a​b​e​l​.​t​e​x​t​​=​​i​t​e​m​.​n​a​m​e​
​​​​c​e​l​l​.​s​e​r​i​a​l​N​u​m​b​e​r​L​a​b​e​l​.​t​e​x​t​​=​​i​t​e​m​.​s​e​r​i​a​l​N​u​m​b​e​r​
​​​​c​e​l​l​.​v​a​l​u​e​L​a​b​e​l​.​t​e​x​t​​=​​"​$​\​(​i​t​e​m​.​v​a​l​u​e​I​n​D​o​l​l​a​r​s​)​"​
​​​​r​e​t​u​r​n​​c​e​l​l​
}​

First,thereuseidentifierisupdatedtoreflectyournewsubclass.Thecodeattheendof
thismethodisfairlyobvious–foreachlabelonthecell,setitstexttosomeproperty
fromtheappropriateItem.


Buildandruntheapplication.Thenewcellsnowloadwiththeirlabelspopulatedwiththe
valuesfromeachItem.



DynamicCellHeights

Currently,thecellshaveafixedheightof65points.Itismuchbettertoallowthecontent
ofthecelltodriveitsheight.Thatway,ifthecontenteverchanges,thetableviewcell’s
heightcanchangeautomatically.
Youcanachievethisgoal,asyouhaveprobablyguessed,withAutoLayout.The
UITableViewCellneedstohaveverticalconstraintsthatwillexactlydeterminethe
heightofthecell.Currently,ItemCelldoesnothavesufficientconstraintsforthis.You
needtoaddaconstraintbetweenthetwoleftlabelsthatfixestheverticalspacingbetween
them.
OpenMain.storyboard.Control-dragfromthenameLabeltothe
serialNumberLabelandselectVerticalSpacing.
NowopenItemsViewController.swiftandupdateviewDidLoad(_:)totell
thetableviewthatitshouldcomputethecellheightsbasedontheconstraints.
o​v​e​r​r​i​d​e​​f​u​n​c​​v​i​e​w​D​i​d​L​o​a​d​(​)​​{​
​​​​s​u​p​e​r​.​v​i​e​w​D​i​d​L​o​a​d​(​)​
​​​​/​/​​G​e​t​​t​h​e​​h​e​i​g​h​t​​o​f​​t​h​e​​s​t​a​t​u​s​​b​a​r​
​​​​l​e​t​​s​t​a​t​u​s​B​a​r​H​e​i​g​h​t​​=​​U​I​A​p​p​l​i​c​a​t​i​o​n​.​s​h​a​r​e​d​A​p​p​l​i​c​a​t​i​o​n​(​)​.​s​t​a​t​u​s​B​a​r​F​r​a​m​e​.​h​e​i​g​h​t​
​​​​l​e​t​​i​n​s​e​t​s​​=​​U​I​E​d​g​e​I​n​s​e​t​s​(​t​o​p​:​​s​t​a​t​u​s​B​a​r​H​e​i​g​h​t​,​​l​e​f​t​:​​0​,​​b​o​t​t​o​m​:​​0​,​​r​i​g​h​t​:​​0​)​
​​​​t​a​b​l​e​V​i​e​w​.​c​o​n​t​e​n​t​I​n​s​e​t​​=​​i​n​s​e​t​s​
​​​​t​a​b​l​e​V​i​e​w​.​s​c​r​o​l​l​I​n​d​i​c​a​t​o​r​I​n​s​e​t​s​​=​​i​n​s​e​t​s​
​​​​t​a​b​l​e​V​i​e​w​.​r​o​w​H​e​i​g​h​t​​=​​6​5​
​​​​t​a​b​l​e​V​i​e​w​.​r​o​w​H​e​i​g​h​t​​=​​U​I​T​a​b​l​e​V​i​e​w​A​u​t​o​m​a​t​i​c​D​i​m​e​n​s​i​o​n​
​​​​t​a​b​l​e​V​i​e​w​.​e​s​t​i​m​a​t​e​d​R​o​w​H​e​i​g​h​t​​=​​6​5​
}​

UITableViewAutomaticDimensionisthedefaultvalueforrowHeight,sowhile
itisnotnecessarytoadd,itisusefulforunderstandingwhatisgoingon.Settingthe
estimatedRowHeightpropertyonthetableviewcanimproveperformance.Instead
ofaskingeachcellforitsheightwhenthetableviewloads,settingthispropertyallows
someofthatperformancecosttobedeferreduntiltheuserstartsscrolling.
Buildandruntheapplication.Theapplicationwilllookthesameasitdidbefore.Inthe

nextsection,youwilllearnaboutatechnologycalledDynamicTypethatwilltake
advantageoftheautomaticallyresizingtableviewcells.



DynamicType
Creatinganinterfacethatappealstoeveryonecanbedaunting.Somepeopleprefermore
compactinterfacessotheycanseemoreinformationatatime.Othersmightwanttobe
abletoeasilyseeinformationataglance,orperhapstheyhavepooreyesight.Inshort:
peoplehavedifferentneeds.Gooddevelopersstrivetomakeappsthatmeetthoseneeds.
DynamicTypeisatechnologythathelpsrealizethisgoalbyprovidingspecifically
designedtextstylesthatareoptimizedforlegibility.Userscanselectoneofseven
preferredtextsizesfromwithinApple’sSettingsapplication(plusafewadditionallarger
sizesfromwithintheAccessibilitysection),andappsthatsupportDynamicTypewillhave
theirfontsscaledappropriately.Inthissection,youwillupdateItemCelltosupport
DynamicType.Figure11.6showstheapplicationrenderedatthesmallestandlargest
user-selectableDynamicTypesizes.
Figure11.6ItemCellwithDynamicTypesupported

TheDynamicTypesystemiscenteredaroundtextstyles.Whenafontisrequestedfora
giventextstyle,thesystemwillconsidertheuser’spreferredtextsizeinassociationwith
thetextstyletoreturnanappropriatelyconfiguredfont.Figure11.7showsthesix
differenttextstyles.


Figure11.7Differenttextstyles

OpenMain.storyboard.Let’supdatethelabelstousethetextstylesinsteadoffixed
fonts.SelectthenameLabelandvalueLabelandopentheattributesinspector.Clickonthetext
icontotherightofFont.ForFont,chooseTextStyles-Body(Figure11.8).Repeatthesame

stepsfortheserialNumberLabel,choosingtheCaption1textstyle.
Figure11.8Changingthetextstyle

Nowlet’schangethepreferredfontsize.YoudothisthroughtheSettingsapplication.
Buildandruntheapplication.PresstheHomebutton(oruseHomefromtheHardware


menu)andopenApple’sSettingsapplication.UnderGeneral,selectAccessibilityandthen
LargerText.(Onanactualdevice,thismenuisaccessedinSettingsunderDisplay&Brightness
andthenTextSize.)Dragthesliderallthewaytothelefttosetthefontsizetothesmallest
value(Figure11.9).PresstheHomebuttonagaintosavethesechanges.
Figure11.9Textsizesettings

Buildandruntheapplication.(Ifyouswitchbacktotheapplication,eitherusingthetask
switcherorthroughtheHomescreen,youwillnotseethechanges.Youwillfixthatinthe
nextsection.)Addsomeitemstothetableviewandyouwillseethenewsmallerfont
sizesinaction.

Respondingtouserchanges
Whentheuserchangesthepreferredtextsizeandreturnstotheapplication,thetableview
willgetreloaded.Unfortunately,thelabelswillnotknowaboutthenewpreferredtext


size.Tofixthis,youneedtoupdatethelabelsmanually.
OpenItemCell.swiftandaddanewmethodthatupdatesallthreelabels.
f​u​n​c​​u​p​d​a​t​e​L​a​b​e​l​s​(​)​​{​
​​​​l​e​t​​b​o​d​y​F​o​n​t​​=​​U​I​F​o​n​t​.​p​r​e​f​e​r​r​e​d​F​o​n​t​F​o​r​T​e​x​t​S​t​y​l​e​(​U​I​F​o​n​t​T​e​x​t​S​t​y​l​e​B​o​d​y​)​
​​​​n​a​m​e​L​a​b​e​l​.​f​o​n​t​​=​​b​o​d​y​F​o​n​t​
​​​​v​a​l​u​e​L​a​b​e​l​.​f​o​n​t​​=​​b​o​d​y​F​o​n​t​
​​​​l​e​t​​c​a​p​t​i​o​n​1​F​o​n​t​​=​​U​I​F​o​n​t​.​p​r​e​f​e​r​r​e​d​F​o​n​t​F​o​r​T​e​x​t​S​t​y​l​e​(​U​I​F​o​n​t​T​e​x​t​S​t​y​l​e​C​a​p​t​i​o​n​1​)​

​​​​s​e​r​i​a​l​N​u​m​b​e​r​L​a​b​e​l​.​f​o​n​t​​=​​c​a​p​t​i​o​n​1​F​o​n​t​
}​

NowopenItemsViewController.swiftandcallthismethodin
tableView(_:cellForRowAtIndexPath:).
o​v​e​r​r​i​d​e​​f​u​n​c​​t​a​b​l​e​V​i​e​w​(​t​a​b​l​e​V​i​e​w​:​​U​I​T​a​b​l​e​V​i​e​w​,​
​​​​c​e​l​l​F​o​r​R​o​w​A​t​I​n​d​e​x​P​a​t​h​​i​n​d​e​x​P​a​t​h​:​​N​S​I​n​d​e​x​P​a​t​h​)​​-​>​​U​I​T​a​b​l​e​V​i​e​w​C​e​l​l​​{​
​​​​​​​​/​/​​G​e​t​​a​​n​e​w​​o​r​​r​e​c​y​c​l​e​d​​c​e​l​l​
​​​​​​​​l​e​t​​c​e​l​l​​=​​t​a​b​l​e​V​i​e​w​.​d​e​q​u​e​u​e​R​e​u​s​a​b​l​e​C​e​l​l​W​i​t​h​I​d​e​n​t​i​f​i​e​r​(​"​U​I​T​a​b​l​e​V​i​e​w​C​e​l​l​"​,​
​​​​​​​​​​​​f​o​r​I​n​d​e​x​P​a​t​h​:​​i​n​d​e​x​P​a​t​h​)​​a​s​!​​I​t​e​m​C​e​l​l​
​​​​​​​​/​/​​U​p​d​a​t​e​​t​h​e​​l​a​b​e​l​s​​f​o​r​​t​h​e​​n​e​w​​p​r​e​f​e​r​r​e​d​​t​e​x​t​​s​i​z​e​
​​​​​​​​c​e​l​l​.​u​p​d​a​t​e​L​a​b​e​l​s​(​)​
​​​​​​​​l​e​t​​i​t​e​m​​=​​i​t​e​m​S​t​o​r​e​.​a​l​l​I​t​e​m​s​[​i​n​d​e​x​P​a​t​h​.​r​o​w​]​
​​​​​​​​c​e​l​l​.​n​a​m​e​L​a​b​e​l​.​t​e​x​t​​=​​i​t​e​m​.​n​a​m​e​
​​​​​​​​c​e​l​l​.​s​e​r​i​a​l​N​u​m​b​e​r​L​a​b​e​l​.​t​e​x​t​​=​​i​t​e​m​.​s​e​r​i​a​l​N​u​m​b​e​r​
​​​​​​​​c​e​l​l​.​v​a​l​u​e​L​a​b​e​l​.​t​e​x​t​​=​​"​$​\​(​i​t​e​m​.​v​a​l​u​e​I​n​D​o​l​l​a​r​s​)​"​
​​​​​​​​r​e​t​u​r​n​​c​e​l​l​
}​

Buildandruntheapplication.GointoSettingsandchangethepreferredreadingsizetothe
largestsize.Unlikebefore,youcannowswitchbacktoHomepwner,eitherbyopeningthe
taskswitcherorthroughtheHomescreen,andthetableviewwillupdatetoreflectthe
newpreferredtextsize.



BronzeChallenge:CellColors
UpdatetheItemCelltodisplaythevalueInDollarsingreenifthevalueisless
than50andredifthevalueisgreaterthanorequalto50.




12
StackViews
YouhavebeenusingAutoLayoutthroughoutthisbooktocreateflexibleinterfacesthat
scaleacrossdevicetypesandsizes.AutoLayoutisaverypowerfultechnology,butwith
thatpowercomescomplexity.Layingoutaninterfacewelloftenneedsalotofconstraints,
anditcanbedifficulttocreatedynamicinterfacesduetotheneedtoconstantlyaddand
removeconstraints.
Often,aninterface(orasubsectionoftheinterface)canbelaidoutinalinearfashion.
Let’sthinkaboutsomeoftheotherapplicationsyouhavewritteninthisbook.TheQuiz
applicationthatyouwroteinChapter1consistedoffoursubviewsthatwerelaidout
vertically.ThesameistruefortheWorldTrotterapplicationthatyouwrote:the
ConversionViewControllerhadaverticalinterfaceconsistingofatextfieldanda
fewlabels.
Interfacesthathavealinearlayoutaregreatcandidatesforusingastackview.Astack
viewisaninstanceofUIStackViewthatallowsyoutocreateaverticalorhorizontal
layoutthatiseasytolayoutandmanagesmostoftheconstraintsthatyouwouldtypically
havetomanageyourself.Perhapsbestofall,youareabletoneststackviewswithinother
stackviews,whichallowsyoutocreatetrulyamazinginterfacesinafractionofthetime.
Inthischapter,youaregoingtocontinueworkingonHomepwnertocreateaninterfacefor
displayingthedetailsofaspecificItem.Theinterfacethatyoucreatewillconsistof
multiplenestedstackviews,bothverticalandhorizontal(Figure12.1).


Figure12.1Homepwnerwithstackviews


UsingUIStackView
YouaregoingtocreateaninterfaceforeditingthedetailsforanItem.Youwillgetthe

basicinterfaceworkinginthischapter,andthenyouwillfinishimplementingthedetails
inChapter13.
Atthetoplevel,youwillhaveaverticalstackviewwithfourelementsdisplayingthe
item’sname,serialnumber,value,anddatecreated(Figure12.2).
Figure12.2Verticalstackviewlayout

OpenyourHomepwnerprojectandthenopenMain.storyboard.DraganewView
Controllerfromtheobjectlibraryontothecanvas.DragaVerticalStackViewfromtheobject
libraryontotheviewfortheViewController.Addconstraintstothestackviewtopinittothe
leadingandtrailingmargins,andpinthetopandbottomedgestobe8pointsfromthetop
andbottomlayoutguides.
NowdragfourinstancesofUILabelfromtheobjectlibraryontothestackview.From
toptobottom,givetheselabelsthetext“Name,”“Serial,”“Value,”and“DateCreated.”
(Figure12.3).


Figure12.3Labelsaddedtothestackview

Youcanseeaproblemrightaway:thelabelsallhavearedborder(indicatinganAuto
Layoutproblem)andthereisawarningthatsomeviewsareverticallyambiguous.There
aretwowaysyoucanfixthisissue:byusingAutoLayout,orbyusingapropertyonthe
stackview.Let’sworkthroughtheAutoLayoutsolutionfirstbecauseithighlightsan
importantaspectofAutoLayout.

Implicitconstraints
YoulearnedinChapter3thateveryviewhasanintrinsiccontentsize.Youalsolearned
thatifyoudonotspecifyconstraintsthatexplicitlydeterminethewidthorheight,the
viewwillderiveitswidthorheightfromitsintrinsiccontentsize.Howdoesthiswork?
Itdoesthisusingimplicitconstraintsderivedfromaview’scontenthuggingprioritiesand
itscontentcompressionresistancepriorities.Aviewhasoneoftheseprioritiesforeach

axis:
horizontalcontenthuggingpriority


verticalcontenthuggingpriority
horizontalcontentcompressionresistancepriority
verticalcontentcompressionresistancepriority
Contenthuggingpriorities
Thecontenthuggingpriorityislikearubberbandthatisplacedaroundaview.Therubber
bandmakestheviewnotwanttobebiggerthanitsintrinsiccontentsizeinthatdimension.
Eachpriorityisassociatedwithavaluefrom0to1000.Avalueof1000meansthata
viewcannotgetbiggerthanitsintrinsiccontentsizeonthatdimension.
Let’slookatanexamplewithjustthehorizontaldimension.Sayyouhavetwolabelsnext
tooneanotherwithconstraintsbothbetweenthetwoviewsandbetweeneachviewandits
superview,asshowninFigure12.4.
Figure12.4Twolabelssidebyside

Thisworksgreatuntilthesuperviewbecomeswider.Atthatpoint,whichlabelshould
becomewider?Thefirstlabel,thesecondlabel,orboth?AsFigure12.5shows,the
interfaceiscurrentlyambiguous.
Figure12.5Ambiguouslayout

Thisiswherethecontenthuggingprioritybecomesrelevant.Theviewwiththehigher
contenthuggingpriorityistheonethatdoesnotstretch.Youcanthinkaboutthepriority
valueasthe“strength”oftherubberband.Thehigherthepriorityvalue,thestrongerthe


rubberband,andthemoreitwantstohugtoitsintrinsiccontentsize.
Contentcompressionresistancepriorities
Thecontentcompressionresistanceprioritiesdeterminehowmuchaviewresistsgetting

smallerthanitsintrinsiccontentsize.ConsiderthesametwolabelsfromFigure12.4.
Whatwouldhappenifthesuperview’swidthdecreased?Oneofthelabelswouldneedto
truncateitstext(Figure12.6).Butwhichone?
Figure12.6Compressedambiguouslayout

Theviewwiththegreatercontentcompressionresistancepriorityistheonethatwillresist
compressionand,therefore,nottruncateitstext.
Withthisknowledge,youcannowfixtheproblemwiththestackview.
SelecttheDateCreatedlabelandopenitssizeinspector.FindtheVerticalContentHugging
Priorityandloweritto249.Nowtheotherthreelabelshaveahighercontenthugging
priority,sotheywillallhugtotheirintrinsiccontentheight.TheDateCreatedlabelwill
stretchtofillintheremainingspace.

Stackviewdistribution
Let’stakealookatanotherwayofsolvingtheproblem.Stackviewshaveanumberof
propertiesthatdeterminehowtheircontentislaidout.
Selectthestackview,eitheronthecanvasorusingthedocumentoutline.Openits
attributesinspectorandfindthesectionatthetoplabeledStackView.Oneoftheproperties
thatdetermineshowthecontentislaidoutistheDistributionproperty.Currentlyitissetto
Fill,whichletstheviewslayouttheircontentbasedontheirintrinsiccontentsize.Change
thevaluetoFillEqually.Thiswillresizethelabelssothattheyallhavethesameheight,
ignoringtheintrinsiccontentsize(Figure12.7).Besuretoreadthedocumentationforthe
otherdistributionvaluesthatastackviewcanhave.


×