12/3/2015
BeginningAutoLayoutiniOS6:Part2/2RayWenderlich
Beginning Auto Layout in iOS 6: Part
2/2
MatthijsHollemans onSeptember19,2012
Updatenote:Checkoutournewerversionofthistutorial,updatedto
SwiftandiOS8:BeginningAutoLayoutTutorialinSwift:Part2.
Thistutorialisanabbreviatedversionofoneofthechaptersfromour
newbookiOS6ByTutorials.MatthijsHollemanswrotethisthe
sameguywhowrotetheiOSApprenticeSeries.Enjoy!
Inpart1ofthistutorialyousawthattheoldstrutsandsprings
modelformakinguserinterfacescannoteasilysolvealllayout
problems.ThenewAutoLayoutfeaturefromiOS6isthesolution,
butbecausethistechnologyissopowerfulitisalsoabitmoretricky
touse.
Inthissecondpartandfinalpartofthetutorialseries,youllcontinue
learningallaboutconstraintsandhowtoapplythem!
As bold as a user constraint
MaybeyounoticedthatsomeoftheTbarsinthecanvasarethickerthanothers.Theboldonesarecalleduser
constraints,andunlikethethinonesyoucandeletethem.However,whenyoudeleteauserconstraint,Interface
Builderwilloftenputanondeletableconstraintinitsplace.Youwillsoonseewhy.
IntheDocumentOutline,userconstraintshaveablueicon:
SelecttheVerticalSpace(40)constraintandtaptheDeletekeyonyourkeyboard.TheTbarbetweenthetwobuttons
disappearsandisreplacedbyanewVerticalSpaceconstraintthatgoesallthewaytothebottom:
http://www.raywenderlich.com/20897/beginningautolayoutpart2of2
1/30
12/3/2015
BeginningAutoLayoutiniOS6:Part2/2RayWenderlich
Thisnewconstrainthasapurpleiconanddoesnothaveaboldline,meaningthatyoucannotdeletethisone.Thetwo
buttonsarenolongerconnectedvertically,althoughtheyarestillleftalignedduetotheLeadingAlignmentconstraint.
Whydoesthishappen?WhydoesInterfaceBuilderattachanewVerticalConstrainttothebutton,eventhoughyoujust
toldittodeletesuchaconstraint?Theansweristhis:
Foreachviewtheremustalwaysbeenoughconstraintstodeterminebothitspositionandsize.
ThatisthemostimportantruletorememberwhenitcomestousingAutoLayout.Iftherearentenoughconstraints,then
AutoLayoutwillbeunabletocalculatewhereyourviewsshouldbepositionedorhowbigtheyshouldbe.Suchalayout
isconsideredtobeinvalid.Youwillseeexamplesofsuchinvalidlayoutslateron.
InterfaceBuildertriesveryhardtopreventyoufrommakinglayoutsthatareinvalid.Thesizeofthesetwobuttonsis
knownbecausebuttonsknowhowbigtheyshouldbe,basedontheirtext,backgroundimage,andsoonintrinsic
contentsize,remember?Sothatsnotaproblem.TheXpositionofthetopbuttonisalsoknownbecauseitsleftedgeis
alignedwiththebottombutton,andthebottombuttonisalwayshorizontallycentered.TheonlyunknownistheY
position.
Previously,thetwobuttonswereconnectedwithaVerticalSpace.ThatwasenoughtodeterminetheYpositionofthe
topbutton.ButifyoudeletethatVerticalSpace,thenthetopbuttonhasnothingtoanchoritverticallyintheview.It
cannotjustfloattherebecausethenAutoLayouthasnowaytodeterminewhatitsYcoordinateshouldbe.
Topreventthisfromhappening,InterfaceBuilderneedstopinthebuttonsomewhereandthebottomedgeisclosest.
http://www.raywenderlich.com/20897/beginningautolayoutpart2of2
2/30
12/3/2015
BeginningAutoLayoutiniOS6:Part2/2RayWenderlich
Funnilyenough,ifyouruntheappandfliptolandscape,itstillseemstowork.Thescreenlooksexactlythesameasit
didbefore.Thatistrue,butyourdesignisfundamentallydifferent:bothbuttonsarenowconnectedtothebottomofthe
window.Thismeansthatifthebottombuttonmoves,thetoponedoesntmovewithit.(Notethateithersolutionisfine,it
justdependsonwhatyouwantyourapptodo.Butinthisexample,youwanttohaveaverticalconnectionbetweenthe
twobuttons.)
Toillustratethis,selecttheVerticalSpaceconstraintbetweenthelowerbuttonandthescreensedge.Gointothe
Attributesinspector.ItsConstantshouldcurrentlyreadAuto,andStandardischeckedbecausethisisastandard
marginspace.Changeitto40.
Becausethebuttonsarenotconnected,onlythelowerbuttonmovesupwardthetopbuttonstaysput:
NoticethatchangingtheConstantvalueoftheconstraintpromotedittoabolduserconstraint.
Needles and pins
Letsconnectthetwobuttonsagain.Sofaryouhavemadeconstraintsbydraggingthebuttonsonthecanvas,butyou
canalsomakethemafterwards.HolddowntheCmdkeyandclickbothbuttonstoselectthem.FromtheEditormenu,
choosePin\VerticalSpacing.
Youcanalsousethelittlepanelinthebottomrightcornertomakethisconstraint:
Itpopsupthefollowingmenu:
http://www.raywenderlich.com/20897/beginningautolayoutpart2of2
3/30
12/3/2015
BeginningAutoLayoutiniOS6:Part2/2RayWenderlich
Regardlessofthemethodyouchoose,thisaddsanewconstraintbetweenthetwobuttons:
ThenewconstraintisaVerticalSpaceconstraintwithaConstantof20points.Thatisbecausethedistancebetweenthe
twobuttonswas20pointsatthetimeyoumadethisconnection.
NoticethattheoldVerticalSpacefromtheuppermostbuttontothebottomedgeisstillthere.Thisconstrainttheone
thatsaysVerticalSpace(104)isnolongerneeded,sodeleteit.
Previouslywhenyoudeletedablueconstraint,apurpleonetookitsplace.Nowthatdoesnothappen,becausethe
remainingconstraintsaresufficienttopositionalltheviews.InterfaceBuilderonlyaddsnewconstraintswhenthe
existingonesarenolongeradequate.
Youshouldnowhavethefollowingconstraints:
http://www.raywenderlich.com/20897/beginningautolayoutpart2of2
4/30
12/3/2015
BeginningAutoLayoutiniOS6:Part2/2RayWenderlich
SelectthebottomVerticalSpace(byclickingonthecanvas)andchangeitsConstantfrom40backtoStandard.This
shouldnotonlymovethebottombuttondownwards,butthetopbuttonaswell,becausetheyareconnectedagain.
A little runtime excursion
Youveseenabitofthebasicsnow:youknowhowtoplacecontrolsusingtheguides,howtoalignthemrelativetoone
another,andhowtoputspacebetweencontrols.Overthecourseofthistutorialyouwillalsousetheotheroptionsfrom
theAlignandPinmenus.
PlayingwiththisinInterfaceBuilderisallwellandgood,butletsseehowthisworksatruntime.Addthefollowing
methodtoViewController.m:
- (IBAction)buttonTapped:(UIButton *)sender
{
if ([[sender titleForState:UIControlStateNormal] isEqualToString:@"X"])
[sender setTitle:@"A very long title for this button"
forState:UIControlStateNormal];
else
[sender setTitle:@"X" forState:UIControlStateNormal];
}
Thissimplytogglesbetweenalongtitleandashorttitleforthebuttonthattriggeredtheevent.Connectthisaction
methodtobothofthebuttonsinInterfaceBuilder:CtrldragfromeachbuttontoFilesOwnerandselectbuttonTapped:in
thepopup.
Runtheappandtapthebuttonstoseehowitbehaves.Performthetestinbothportraitandlandscapeorientations.
http://www.raywenderlich.com/20897/beginningautolayoutpart2of2
5/30
12/3/2015
BeginningAutoLayoutiniOS6:Part2/2RayWenderlich
Regardlessofwhichbuttonhasthelongtitleandwhichhastheshorttitle,thelayoutalwayssatisfiestheconstraintsyou
havegivenit:
Thelowerbuttonisalwayscenteralignedinthewindow,horizontally.
Thelowerbuttonalwayssits20pointsfromthebottomofthewindow.
Thetopbuttonisalwaysleftalignedwiththelowerbutton.
Thatistheentirespecificationforyouruserinterface.
Forfun,selectbothbuttonsinInterfaceBuilderandfromtheAlignmenupickRightEdges.Nowruntheappagainand
noticethedifferences.
Repeat,butnowchooseAlign\HorizontalCenters.Thatwillalwayscenterthetopbuttonwithrespecttothebottom
button.Runtheappandseehowthebuttonsactwhenyoutapthem.
Fixing the width
ThePinmenuhasanoptionforWidthsEqually.Ifyousetthisconstraintontwoviews,thenAutoLayoutwillalways
makebothviewsequallywide,basedonwhichoneisthelargest.Letsplaywiththatforaminute.
SelectbothbuttonsandchoosePin\WidthsEqually.Thisaddsanewconstrainttobothbuttons:
http://www.raywenderlich.com/20897/beginningautolayoutpart2of2
6/30
12/3/2015
BeginningAutoLayoutiniOS6:Part2/2RayWenderlich
Note:Ifyougetanextraunintendedconstraintbetweenoneofthebuttonsandthesuperview,selectthetwo
buttonsandselectAlign\HorizontalCentersagain.
Youhaveseenthistypeofconstraintbefore,inthefirstpartofthistutorial.ItlooksliketheusualTbarbutinthemiddleit
hasacirclewithanequalsign.
IntheDocumentOutlinethisshowsupasasingleEqualWidthsconstraint:
Changingthelabeltextononebuttonwillnowchangethesizeoftheotheroneaswell.
ChangethebottombuttonslabeltoX,justtomakeitreallysmall.Youwillnoticethatthetopbuttonnolongerfitsits
text:
SohowdoesInterfaceBuilderknowwhichbuttonssizetouseforbothofthem?Ifyoupaycloseattention,youllseethat
aWidthconstraintwasaddedtothebuttonwiththetruncatedtext:
http://www.raywenderlich.com/20897/beginningautolayoutpart2of2
7/30
12/3/2015
BeginningAutoLayoutiniOS6:Part2/2RayWenderlich
InterfaceBuilderdoesthistoforcethebuttontobecomesmallerthanwhatitwouldideallybe,inordertocomplywiththe
EqualWidthsconstraint.
Obviouslythisisnotwhatyouwant,soselectthetopbuttonandchooseSizetoFitContentfromtheEditormenu(or
pressCmd=).Nowthetextfitsinsidethebuttonagainorrather,thebuttonfitsaroundthetextandtheWidth
constraintisgone.
Runtheappandtapthebuttons.Thebuttonsalwayshavethesamewidth,regardlessofwhichonehasthelargest
label:
http://www.raywenderlich.com/20897/beginningautolayoutpart2of2
8/30
12/3/2015
BeginningAutoLayoutiniOS6:Part2/2RayWenderlich
Ofcourse,whenbothlabelsareveryshort,bothbuttonswillshrinkequally.Afterall,unlessthereisaconstraintthat
prevents,buttonswillsizethemselvestofittheircontentexactly,nomore,noless.Whatwasthatcalledagain?Right,the
intrinsiccontentsize.
IntrinsicContentSize
BeforeAutoLayout,youalwayshadtotellbuttonsandothercontrolshowbigtheyshouldbe,eitherbysettingtheir
frameorboundspropertiesorbyresizingtheminInterfaceBuilder.Butitturnsoutthatmostcontrolsareperfectly
capableofdetermininghowmuchspacetheyneed,basedontheircontent.
Alabelknowshowwideandtallitisbecauseitknowsthelengthofthetextthathasbeensetonit,aswellasthe
fontsizeforthattext.Likewiseforabutton,whichmightcombinethetextwithabackgroundimageandsome
paddingfortheroundedcorners.
Thesameistrueforsegmentedcontrols,progressbars,andmostothercontrols,althoughsomemayonlyhavea
predeterminedheightbutanunknownwidth.
Thisisknownastheintrinsiccontentsize,anditisanimportantconceptinAutoLayout.Youhavealreadyseenit
inactionwiththebuttons.AutoLayoutasksyourcontrolshowbigtheyneedtobeandlaysoutthescreenbased
onthatinformation.
YoucanpreventthisbysettinganexplicitWidthorHeightconstraintonacontrol.Ifyouresizethecontrolbyhand,
thenInterfaceBuilderwillsetsuchanexplicitconstraintforyou.WiththeSizetoFitContentcommand,you
removeanyfixedWidthorHeightconstraintsandletthecontroldetermineitsintrinsiccontentsizeagain.
Usuallyyouwanttousetheintrinsiccontentsize,buttherearesomecaseswhereyoumaynotwanttodothat.
ImaginewhathappenswhenyousetanimageonaUIImageViewifthatimageismuchlargerthanthescreen.You
usuallywanttogiveimageviewsafixedwidthandheightandscalethecontent,unlessyouwanttheviewtoresize
tothedimensionsoftheimage.
http://www.raywenderlich.com/20897/beginningautolayoutpart2of2
9/30
12/3/2015
BeginningAutoLayoutiniOS6:Part2/2RayWenderlich
SowhathappenswhenoneofthebuttonshasafixedWidthconstraintonit?Buttonscalculatetheirownsize,butyou
canoverridethisbygivingthemafixedwidth.SelectthetopbuttonandchoosePin\Widthfromthemenu.Thisaddsa
solidTbarbelowthebutton:
Becausethissortofconstraintonlyappliestothebuttonitself,nottoitssuperview,itislistedintheDocumentOutline
belowthebuttonobject.Inthiscase,youhavefixedthebuttontoawidthof73points.
Runtheappandtapthebuttons.Whathappens?Thebuttontextdoeschange,butitgetstruncatedbecausethereisnot
enoughroom:
Becausethetopbuttonhasafixedwidthconstraintandbothbuttonsarerequiredtobethesamesize,theywillnever
shrinkorgrow.
Note:YouprobablywouldntsetaWidthconstraintonabuttonbydesignitisbesttoletthebuttonuseitsintrinsic
sizebutifyoueverrunintoalayoutproblemwhereyouexpectyourcontrolstochangesizeandtheydont,then
http://www.raywenderlich.com/20897/beginningautolayoutpart2of2
10/30
12/3/2015
BeginningAutoLayoutiniOS6:Part2/2RayWenderlich
doublechecktomakesureInterfaceBuilderdidntsneakafixedWidthconstraintinthere.
Playaroundwiththisstuffforabittogetthehangofpinningandaligningviews.Getafeelforit,becausenoteverything
isimmediatelyobvious.JustrememberthattheremustalwaysbeenoughconstraintssothatAutoLayoutcandetermine
thepositionandsizeforallviews.
Gallery example
Youshouldnowhaveanideaofwhatconstraintsareandhowyoucanbuildupyourlayoutsbyforgingrelationships
betweenthedifferentviews.Inthefollowingsections,youwillseehowtouseAutoLayoutandconstraintstocreate
layoutsthatmeetrealworldscenarios.
Letspretendyouwanttomakeanappthathasagalleryofyourfavoriteprogrammers.Itlookslikethisinportraitand
landscape:
http://www.raywenderlich.com/20897/beginningautolayoutpart2of2
11/30
12/3/2015
BeginningAutoLayoutiniOS6:Part2/2RayWenderlich
Thescreenisdividedintofourequalquarters.Eachquarterhasanimageviewandalabel.Howwouldyouapproach
this?
Letsstartbysettingupthebasicapp.YoucanuseyourexistingConstraintsappbydeletingthebuttonsandreusing
theview.
Or,youcancreateanewprojectusingtheSingleViewApplicationtemplateandnameitasyoulike,forinstance,
Gallery.Thiswilljustuseanib,sodisablethestoryboardsoption.
OpenViewController.xib.FromtheObjectLibrary,dragaplainviewobjectontothecanvas.Resizetheviewsothatitis
160by230points,andchangeitsbackgroundcolortobesomethingotherthanwhite(Imademinegreen):
http://www.raywenderlich.com/20897/beginningautolayoutpart2of2
12/30
12/3/2015
BeginningAutoLayoutiniOS6:Part2/2RayWenderlich
Thisviewhasfourconstraintstokeepitinplace.Unlikeabuttonorlabel,aplainUIViewdoesnothaveanintrinsic
contentsize.Theremustalwaysbeenoughconstraintstodeterminethepositionandsizeofeachview,sothisviewalso
needsconstraintstotellitwhatsizeitneedstobe.
Youmaywonder,wherearethesesizeconstraints?Inthiscase,thesizeoftheviewisimpliedbythesizeofthe
superview.TheconstraintsinthislayoutaretwoHorizontalSpacesandtwoVerticalSpaces,andtheseallhavefixed
lengths.YoucanseethisintheDocumentOutline:
Thewidthofthegreenviewiscalculatedbytheformulawidthofsuperviewminus(109+51)anditsheightbythe
formulaheightofsuperviewminus(153+77).Thespaceconstraintsarefixed,sotheviewhasnochoicebuttoresize.
http://www.raywenderlich.com/20897/beginningautolayoutpart2of2
13/30
12/3/2015
BeginningAutoLayoutiniOS6:Part2/2RayWenderlich
Whenyourotatetheapp,thedimensionsofthesuperviewchangefrom320460to480300.Plugthisnewwidthand
heightintotheseformulas,andyoullgetthenewsizeofthegreenview.
Youcanseethisforyourselfwhenyouruntheappandfliptolandscape,butyoucanalsosimulateitdirectlyinInterface
Builder.
SelectthetopmostviewinthenibandgototheAttributesinspector.UndertheSimulatedMetricssection,change
OrientationtoLandscape:
Thisgivesyouaninstantpreviewofwhatthenibslayoutwilllooklikeinlandscapeorientation.Thegreenviewhas
resizedinordertosatisfyitsHorizontalandVerticalSpaceconstraints.
Switchbacktoportraitorientation.
Note:TherearetwomainreasonswhyyouwoulddropaplainUIViewontoanib:a)Youregoingtouseitasa
containerforotherviews,whichhelpswithorganizingthecontentofyournibsorb)Itisaplaceholderforacustom
vieworcontrol,andyouwillalsosetitsClassattributetothenameofyourownUIVieworUIControlsubclass.
YoumaynotalwayswantyourUIViewtoresizewhenthedevicerotates,soyoucanuseconstraintstogivetheviewa
fixedwidthand/orheight.Letsdothatnow.SelectthegreenviewandfromthePinmenu,chooseWidth.Selecttheview
againandchoosePin\Height.
Youhavenowaddedtwonewconstraintstotheview,a160pointWidthconstraintanda230pointHeightconstraint:
http://www.raywenderlich.com/20897/beginningautolayoutpart2of2
14/30
12/3/2015
BeginningAutoLayoutiniOS6:Part2/2RayWenderlich
BecauseWidthandHeightapplytojustthisview,theyarelocatedintheDocumentOutlineundertheViewitself.
Usually,constraintsexpressarelationshipbetweentwodifferentviewsforexample,theHorizontalandVerticalSpace
constraintsarebetweenthegreenviewanditsgraysuperviewbutyoucanconsidertheWidthandHeightconstraints
tobearelationshipbetweentheviewanditself.
Runtheapp.Yup,looksgoodinportrait.Nowflipovertolandscape.Whoops!Notonlydoesitnotlooklikeyouwanted
theviewhaschangedsizeagainbuttheXcodedebugpanehasdumpedanastyerrormessage:
Gallery[68932:11303] Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't
want. Try this: (1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it. (Note: If
you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the
documentation for the UIView property translatesAutoresizingMaskIntoConstraints)
(
"<NSLayoutConstraint:0x754dac0 V:[UIView:0x754e510(230)]>",
"<NSLayoutConstraint:0x754eac0 V:|-(77)-[UIView:0x754e510]
(Names:
'|':UIView:0x754e3a0 )>",
"<NSLayoutConstraint:0x754ea40 V:[UIView:0x754e510]-(153)-|
(Names:
'|':UIView:0x754e3a0 )>",
"<NSAutoresizingMaskLayoutConstraint:0x7558cd0 h=-&- v=-&- UIView:0x754e3a0.width ==
UIWindow:0x71156e0.width - 20>",
"<NSAutoresizingMaskLayoutConstraint:0x74128b0 h=--- v=--- H:
[UIWindow:0x71156e0(320)]>"
)
Will attempt to recover by breaking constraint
http://www.raywenderlich.com/20897/beginningautolayoutpart2of2
15/30
12/3/2015
BeginningAutoLayoutiniOS6:Part2/2RayWenderlich
<NSLayoutConstraint:0x754dac0 V:[UIView:0x754e510(230)]>
Break on objc_exception_throw to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in
<UIKit/UIView.h> may also be helpful.
RememberwhenIsaidthattheremustbeenoughconstraintssothatAutoLayoutcancalculatethepositionsandsizes
ofalltheviews?Well,thisisanexamplewheretherearetoomanyconstraints.WheneveryougettheerrorUnableto
simultaneouslysatisfyconstraints,itmeansthatyourconstraintsareconflictingsomewhere.
Letslookatthoseconstraintsagain:
Therearesixconstraintssetonthegreenview,thefourSpacingconstraintsyousawearlierandthenewWidthand
Heightconstraintsthatyouhavejustsetonit.Sowhereistheconflict?
Well,inportraitmodethereshouldntbeaproblembecausethemathaddsup.Thewidthofthesuperviewis320points.
IfyouaddthelengthsoftheHorizontalSpaceconstraintsandtheWidthoftheview,thenyoushouldalsoendupat320.
ThewayIhavepositionedtheview,thatis:51+160+109=320indeed.Likewise,theverticalconstraintsshouldadd
upto460.
Butwhenyourotatethedevicetolandscape,thewindow(andthereforethesuperview)is480pointswide.Thatmeans
51+160+109+?=480.Thereare160extrapointsthatneedtogosomewhereinthatequationandAutoLayout
doesntknowwheretogetthem.Likewisefortheverticalaxis.
http://www.raywenderlich.com/20897/beginningautolayoutpart2of2
16/30
12/3/2015
BeginningAutoLayoutiniOS6:Part2/2RayWenderlich
Theconflicthereisthateitherthewidthoftheviewisfixedandoneofthemarginsmustbeflexible,orthemarginsare
fixedandthewidthmustbeflexible.Sooneoftheseconstraintshastogo.Intheaboveexample,youwanttheviewto
havethesamewidthinbothportraitandlandscape,sothetrailingHorizontalSpacehasgottogo.
RemovetheHorizontalSpaceattherightandtheVerticalSpaceatthebottom.Thenibshouldlooklikethis:
Nowtheviewhasjusttherightnumberofconstraintstodetermineitssizeandposition,nomore,noless.Runtheapp
andverifythattheerrormessageisgoneandthattheviewstaysthesamesizeafterrotating.
Note:EventhoughInterfaceBuilderdoesitsbesttopreventyoufrommakinginvalidlayouts,itcannotperform
miracles.AtleastAutoLayoutspitsoutadetailederrormessagewhensomethingiswrong.Youwilllearnmore
aboutanalyzingtheseerrormessagesanddiagnosinglayoutproblemsinIntermediateAutoLayoutiniOS6by
Tutorials.
Painting the portraits
Dragalabelontothegreenview.Noticethatnowtheguidesappearwithinthatgreenview,becauseitwillbethe
superviewforthelabel.
http://www.raywenderlich.com/20897/beginningautolayoutpart2of2
17/30
12/3/2015
BeginningAutoLayoutiniOS6:Part2/2RayWenderlich
Positionthelabelinthetopleftcorneragainsttheguides.ThiswilladdtwoSpaceconstraintstoanchorthelabelinthe
topleftcornerofthegreenview:
http://www.raywenderlich.com/20897/beginningautolayoutpart2of2
18/30
12/3/2015
BeginningAutoLayoutiniOS6:Part2/2RayWenderlich
NoticethatthesetwonewHorizontalandVerticalSpaceconstraintsarelistedunderthegreenviewsConstraints
section,notinthemainview.
Nowmovethegreenviewaroundabit.Youllseethatonlytheconstraintsbetweenthegreenviewanditssuperview
change,butthoseforthelabeldont.Thelabelalwaysstaysputinthesameplace,relativetothegreenview.
Selectthelabelandplaceitagainstthebottommargin,horizontallycentered.Thendraganewimageviewobjectonto
thenib,andmakethelayoutlooklikethis:
http://www.raywenderlich.com/20897/beginningautolayoutpart2of2
19/30
12/3/2015
BeginningAutoLayoutiniOS6:Part2/2RayWenderlich
Theimageviewispinnedtothetop,leftandrightedgesofitssuperview,butitsbottomisconnectedtothetopofthe
labelwithastandardspacing.
Downloadtheresourcesforthistutorialandunzipthefile.YouwillfindanImagesfolderaddthisfolderintoyour
project.SetRay.pngastheimagefortheimageview,changetheimageviewsmodetoAspectFitandsetits
backgroundcolortowhite.ChangethelabelstexttosayRay.
Yourlayoutshouldnowlooklikethis:
http://www.raywenderlich.com/20897/beginningautolayoutpart2of2
20/30
12/3/2015
BeginningAutoLayoutiniOS6:Part2/2RayWenderlich
NoticethatInterfaceBuilderhasplacedaHeightconstraintonthelabelnow.Thishappenedthemomentyousetthe
imageontheimageview.
InterfaceBuildertriestopreventwhatareknownasambiguouslayouts.Ifneithertheimageviewnorthelabelhasa
http://www.raywenderlich.com/20897/beginningautolayoutpart2of2
21/30
12/3/2015
BeginningAutoLayoutiniOS6:Part2/2RayWenderlich
fixedheight,thenAutoLayoutdoesntknowbyhowmuchtoscaleeachiftheheightofthegreenviewshouldchange.
(InterfaceBuilderseemstoignorefornowthatthegreenviewactuallyhasafixedHeightconstraintsetonit.)
Letssayatsomepointinyourappthegreenviewbecomes100pointstaller.HowshouldAutoLayoutdistributethese
new100pointsamongthelabelandtheimageview?Doestheimageviewbecome100pointstallerwhilethelabel
staysthesamesize?Ordoesthelabelbecometallerwhiletheimageviewstaysthesame?Dotheybothget50points
extra,orisitsplit25/75,40/60,orinsomeotherpossiblecombination?
AutoLayoutisnotgoingtoguess,soInterfaceBuilderfixesthisproblemforusbygivingthelabelafixedheight.It
couldalsohavegiventheimageviewafixedheight,butthelabelmakesmoresense.
Fornow,letsjustlivewiththeHeightconstraintonthelabel.
Note:ThepropersolutiontothissmalllayoutproblemistochangetheContentCompressionResistancePriority
ofthelabel.Youwilllearnmoreaboutthatlateron.Ifyoucantwait,thengointotheSizeinspectorforthelabel
andsettheverticalContentCompressionResistancePriorityto751.TheHeightconstraintonthelabelshouldnow
disappear.
Adding the other heads
Movethegreenviewontothemainviewstopleftcorner.RecallthatthegreenviewhadHorizontalSpaceandVertical
Spaceconstraintsthatdetermineditspositionintheparentview.Itstillhasthose,buttheyarenowsettoavalueof0
theyarerepresentedbythethickbluelines(withwhiteborders)atthetopandleftedgesofthewindow:
http://www.raywenderlich.com/20897/beginningautolayoutpart2of2
22/30
12/3/2015
BeginningAutoLayoutiniOS6:Part2/2RayWenderlich
Soeventhoughtheviewsitscompletelyinthecorner,itstillneedsconstraintstoanchoritthere.Thinkoftheseas
marginswithavalueof0.
SelectthegreenviewandtapCmdDtoduplicateit.Movetheduplicateintothetoprightcorner:
http://www.raywenderlich.com/20897/beginningautolayoutpart2of2
23/30
12/3/2015
BeginningAutoLayoutiniOS6:Part2/2RayWenderlich
Duplicatetwomoretimesandputthesecopiesinthebottomleftandbottomrightcorners,respectively.
Changethescreendesigntothefollowing:
http://www.raywenderlich.com/20897/beginningautolayoutpart2of2
24/30
12/3/2015
BeginningAutoLayoutiniOS6:Part2/2RayWenderlich
Thosearesomegoodlookingprogrammers!:)
Runtheapp.Itlooksgoodinportrait,butnotsomuchinlandscape:
http://www.raywenderlich.com/20897/beginningautolayoutpart2of2
25/30
12/3/2015
BeginningAutoLayoutiniOS6:Part2/2RayWenderlich
Itshouldbeprettyobviouswhatwentwrong:youvesetafixedwidthandheightonthefourbrightlycoloredcontainer
views,sotheywillalwayshavethosesizes,regardlessofthesizeoftheirsuperview.
SelecttheWidth(160)andHeight(230)constraintsfromallfourviewsanddeletethem.Ifyouruntheappnow,youllget
somethinglikethis.Alsonotverygood:
Thislooksverymuchliketheproblemwesolvedintheintroduction,soifyouthinkbacktohowwesolvedthat,youll
recallthatwegavetheviewsequalwidthsandheights.
SelectallfourcoloredviewsandchoosePin\WidthsEqually.SelecttheviewsagainandchoosePin\HeightsEqually.
Runtheappagainandrotatethedevice.Hmmitstilllooksexactlythesameasbefore.Why?
Well,ifyoulookatthescreenshotyoullseethatalltheviewsdohavethesameheight,andtheyalsoappeartohavethe
samewidth(thegreenandbrownviewsarepartiallyobscuredbytheyellowandblueones),soourconstraintsare
beingmet.Itsjustnotthewidthandheightthatyouwantthemtohave.Theremustbeotherconstraintsthataregetting
intheway.
Sureenough,ifyoulookattheconstraintsontheseviews,youllseethattheyalsohaveHorizontalandVerticalSpace
constraintsthatforcethemintoplace(lookatlistofconstraintsonthemainview,notthefoursubviews):
http://www.raywenderlich.com/20897/beginningautolayoutpart2of2
26/30
12/3/2015
BeginningAutoLayoutiniOS6:Part2/2RayWenderlich
Whatsworse,youcantevendeletethatconstraint.ItsTbarisnotboldandtheconstraintisnotblue,soInterface
Builderputitthereinordertopreventalayoutproblem.
Sowhydoesitdothat?Justsayingthatallfourviewsmusthaveequalsizesisnotenoughtodeterminewhatthose
sizesshouldactuallybe,becauseAutoLayoutdoesnotknowhowthesefourviewsareconnectedtoeachother.They
appearsidebysideinthedesign,buttherearenoactualconstraintsbetweenthem.AutoLayoutdoesnotknowthatit
needstosplitthewindowwidthbetweentheRayandMatthijsboxes.
IfAutoLayoutcantfigurethisoutbyitself,youhavetotellit.
http://www.raywenderlich.com/20897/beginningautolayoutpart2of2
27/30
12/3/2015
BeginningAutoLayoutiniOS6:Part2/2RayWenderlich
SelecttheRayandMatthijsboxesandchoosePin\HorizontalSpacing.Becausetheboxesaresidebyside,thisaddsa
HorizontalSpaceconstraintwithsize0betweenthem,andthatisenoughtoletAutoLayoutknowhowthesetwoviews
arerelated.
Important:InterfaceBuilderdoesnotautomaticallyremovetheleadingHorizontalSpacebetweenthesuperviewand
theyellowbox(theonefromthescreenshotabove),butitdidpromoteittoauserconstraint(afatbar).Youcannow
deletethisspace.Ifyoudont,youwillgetanUnabletosimultaneouslysatisfyconstraintserrorduringruntimewhen
youfliptolandscape.
Runtheapp.Itshouldnowlooklikethis:
Thatlooksabitbetteralready.Thefourboxesnowhaveequalwidths,buttheheightsarestillwrong.Thesolutionis
similar:putaVerticalSpacebetweentheRayandDennisRitchieboxesandremovetheVerticalSpacebetweenthe
DennisRitchieboxandthetopofthewindow.
http://www.raywenderlich.com/20897/beginningautolayoutpart2of2
28/30
12/3/2015
BeginningAutoLayoutiniOS6:Part2/2RayWenderlich
Runtheappagain,andthistimeitlooksallright:
NoticethattheDennisRitchielabelisnotcenteredbelowitsimageview.ThisoriginallyhappenedtomewhenItyped
thattextintothelabel.Thelabelwasinitiallycenteredintheview,butInterfaceBuilderdecideditknewbetterand
replacedthatcenteringconstraintwithaHorizontalSpace.Ifthishappenedtoyou,too,thenselectthatlabelandchoose
Align\HorizontalCenterinContainertofixit.
Aquicknoteontheimageviews:theystretchoutbecauseyouhavenotgiventhemafixedsize.Youmaynotknowit,but
thatsintentionalonyourpart. Theimageviewswouldntfitinlandscapemodeotherwise.However,ifyouwantan
imageviewtokeepitsoriginalaspectratio,thenyoureoutofluck.Youcannotachievethefollowingeffectusing
InterfaceBuilder:
Unfortunately,InterfaceBuilderdoesnotcurrentlyprovideawaytomakeconstraintsthatkeeptheaspectratioofaview
intact.Todothat,youneedtocreateandsettheconstraintsprogrammatically.Youwilllearnhowtodothatin
IntermediateAutoLayoutiniOS6byTutorials.
Tip:YouhaveseenthatyoucanpreviewwhattheUIwilllooklikeinlandscapebychangingtheOrientationsetting
underSimulatedMetrics.YoucanalsotesttheresizingbehaviorofyourviewsdirectlyinInterfaceBuilder.
Selectthemainview.UnderSimulatedMetrics,setSizetoFreeform.Thisaddsresizehandlesaroundyournibthatyou
canusetomolditintoanyshapeyouwant.AutoLayoutwillrecalculatethelayoutonthefly:
http://www.raywenderlich.com/20897/beginningautolayoutpart2of2
29/30
12/3/2015
BeginningAutoLayoutiniOS6:Part2/2RayWenderlich
However,becarefulwiththis.SometimesInterfaceBuilderwillinsertnewconstraintsofitsownwhenyoureresizing,as
itdidhereinthebottomrightcorner(itaddedaHorizontalSpace).Itmayalsodeleteexistingconstraintswhentheyfall
outsideofthenibbounds.
Where To Go From Here?
Ifyouvemadeitthisfar,congratulationsyounowknowwhatAutoLayoutisallabout,andhaveexperimentedwiththe
basics!Buttheresalotlefttolearn
ThetutorialyouhavejustreadisonlythefirsthalfoftheBeginningAutoLayoutchapterfromthebookiOS6byTutorials.
ThesecondhalfteacheshowtouseAutoLayouttocreatemorerealworldscreenlayouts,andeverythingelseyou
needtoknowaboutusingAutoLayoutfromInterfaceBuilder.
Butlikeanyvisualdesigntool,InterfaceBuilderhasitslimitationsandsometimesitjustmakesmoresensetoworkwith
theNSLayoutConstraintobjectsdirectlyfromcode.iOS6byTutorialsdedicatesanentirechaptertothistopic,
IntermediateAutoLayout.SoifyouwanttogettothebottomofAutoLayout,getthebook!
MatthijsHollemans
MatthijsHollemansisanindependentiOSdeveloperanddesignerwholivestocreate
awesomesoftware.HisfocusisoniPadappsbecausehethinkstabletsarewaycooler
thanphones.Wheneverheisnotgluedtohisscreen,Matthijsplaysthepiano,isinto
healthyandnaturalliving,andgoesoutbarefootrunning.Visithiswebsiteat
http://www.hollance.com.
http://www.raywenderlich.com/20897/beginningautolayoutpart2of2
30/30