Auto Layout — ett system för adaptiv positionering av gränssnittselement från Apple, baserat på matematiska begränsningar (constraints). Utvecklat för iOS 6 (2012), gör Auto Layout det möjligt att skapa gränssnitt som visas korrekt på alla enheter — från iPhone SE (4.7″) till iPad Pro (12.9″) och Dynamic Island. Enligt Apple WWDC Session 202 (2024) använder över 90% av apparna i App Store Auto Layout eller dess deklarativa alternativ — SwiftUI layout system. Constraints beskriver beroenden mellan UI-element genom linjära ekvationer: view1.leading = view2.trailing + 8.
Huvudpunkter
Auto Layout — är Apples adaptiva layoutsystem som använder matematiska begränsningar (constraints) för att placera UI-element. Till skillnad från rambaserad layout (frame-based layout), där varje element har fasta koordinater x, y, width, height, beskriver Auto Layout relationer mellan element: «knappen är 8pt från den högra kanten av föräldern» eller «textfältets bredd är lika med halva skärmbredden». Mekanismen är baserad på Cassowary-algoritmen, utvecklad vid University of Washington (Greg J. Badros, 1999) och implementerad av Apple i iOS 6. Cassowary löser ett system av linjära olikheter med prioriteringar — Required (1000), Default High (750), Default Low (250) — vilket gör det möjligt att hantera konflikter mellan begränsningar. Auto Layout stöder tre typer av storlekar: intrinsic (elementets naturliga storlek bestämd av innehållet), explicit (explicit angiven begränsning) och compressible/stretchable (elastiskt läge genom Content Hugging Priority och Compression Resistance Priority).
Varje UI-element i Auto Layout har en Intrinsic Content Size — den naturliga storleken bestämd av dess innehåll. För UILabel beror det på text och teckensnitt, för UIImageView — på bildens dimensioner. Content Hugging Priority (motstånd mot sträckning) och Compression Resistance Priority (motstånd mot komprimering) styr elementets beteende när tillgängligt utrymme ändras. Standardvärden: 251 för hugging och 749 för compression resistance. Om två element konkurrerar om utrymme avgör prioriteten vilket som sträcks ut först. Att förstå dessa prioriteringar är nyckeln till att eliminera Ambiguous Layout (tvetydig layout), som Xcode markerar i debugger.
En constraint beskrivs med en ekvation: view1.attribute = multiplier × view2.attribute + constant. Attribut inkluderar leading, trailing, top, bottom, centerX, centerY, width, height, firstBaseline, lastBaseline. Multiplier används för proportionella relationer (bredd view1 = 0.5 × bredd superview). Constant definierar ett fast avstånd (leading = superview.leading + 16). Interface Builder-verktyg gör det möjligt att visuellt ange constraints genom Ctrl-dra, men komplexa layouter kräver programmatiskt skapande via NSLayoutConstraint eller VFL (Visual Format Language), som Apple rekommenderar att ersätta med NSLayoutConstraint från iOS 9.
Systemet med constraints löses som ett linjärt programmeringsproblem: Cassowary-algoritmen hittar den optimala positioneringen av alla element, och uppfyller alla begränsningar med hänsyn till deras prioriteringar. Om constraints motsäger varandra uppstår Unsatisfiable Layout — ett undantag som Xcode loggar med en detaljerad beskrivning av konflikten. Om constraints inte är tillräckliga för att bestämma positionen för minst ett element uppstår Ambiguous Layout — element visas på en godtycklig position. Apple rekommenderar en minimal uppsättning: för varje element måste position (x, y) och storlek (width, height) anges — explicit eller via intrinsic content size. Constraints kan vara first-class: det ledande elementet (t.ex. superview) och det beroende (barnelementet) skapar en hierarki.
Cassowary använder metoden Sequential Quadratic Programming för att lösa system av linjära olikheter. Varje constraint har en prioritet från 1 till 1000. Required (1000) — obligatorisk begränsning; om den inte kan uppfyllas kraschar appen med NSConstraintException. Default High (750) — rekommenderad; Default Low (250) — minst viktig. Vid en konflikt loosar Cassowary begränsningar med lägre prioritet. Till exempel, om två element kräver fast bredd och skärmen är för smal, loosas constraint med lägre prioritet. I Xcode Debug View Hierarchy (felsökningsverktyg tillgängligt från Xcode 6) markeras endast problem med Required constraints — resten bearbetas utan fel.
UIStackView — en behållare introducerad i iOS 9 (2015), som automatiskt skapar och hanterar constraints för kapslade arrangedSubviews. UIStackView stöder två axlar: horizontal (horisontell layout) och vertical (vertikal). Distribution-inställningar bestämmer utrymmesfördelning: fill (fyllning proportionell mot hugging priority), fillEqually (lika stora), fillProportionally (proportionell mot intrinsic content size), equalSpacing (lika mellanrum), equalCentering (lika avstånd mellan centra). Alignment anger justering tvärs över axeln: fill, leading, center, trailing (för horizontal) eller fill, top, center, bottom (för vertical). UIStackView hanterar automatiskt spacing, baseline alignment och anpassning till Dynamic Type.
import UIKit
class StackViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let stack = UIStackView()
stack.axis = NSLayoutConstraint.Axis.vertical
stack.distribution = .fillEqually
stack.spacing = 8
stack.translatesAutoresizingMaskIntoConstraints = false
let label = UILabel()
label.text = "Auto Layout-guide"
label.font = UIFont.preferredFont(forTextStyle: .headline)
let button = UIButton(type: .system)
button.setTitle("Tillämpa", for: .normal)
stack.addArrangedSubview(label)
stack.addArrangedSubview(button)
view.addSubview(stack)
NSLayoutConstraint.activate([
stack.centerXAnchor.constraint(equalTo: view.centerXAnchor),
stack.centerYAnchor.constraint(equalTo: view.centerYAnchor),
stack.leadingAnchor.constraint(greaterThanOrEqualTo: view.leadingAnchor, constant: 16),
stack.trailingAnchor.constraint(lessThanOrEqualTo: view.trailingAnchor, constant: -16)
])
}
}Koden skapar en vertikal UIStackView med två element (UILabel och UIButton), jämnt fördelade (fillEqually) med ett mellanrum på 8pt. Stacken centreras på skärmen med marginaler från kanterna på minst 16pt. translatesAutoresizingMaskIntoConstraints = false är obligatoriskt vid programmatiskt skapande av constraints — utan det fungerar inte Auto Layout. Hos IT Sectr används UIStackView i 80% av iOS-projektens skärmar för att bygga adaptiva formulär, inställningslistor och kort.
UIStackViews kan kapslas: horisontell stack inuti en vertikal — ett standardmönster för komplexa layouter. Den yttre stacken hanterar rader, den inre — kolumner inom raden. Kombinationen av axis, alignment och distribution på varje nivå ger praktiskt taget obegränsad flexibilitet utan en enda manuell constraint. Apple rekommenderar att använda UIStackView som det primära layoutverktyget i UIKit, och endast använda manuella NSLayoutConstraint för fall som inte täcks av stacken: överlappande vyer, pixelprecision, anpassad bounds-animation.
NSLayoutConstraint — programmerings-API för att skapa individuella begränsningar i kod. Varje constraint skapas via en initierare med parametrar: item, attribute, relatedBy, toItem, attribute, multiplier, constant. Från iOS 9 introducerade Apple Anchor API — en mer läsbar syntax genom egenskaperna view.leadingAnchor, view.trailingAnchor, view.topAnchor, view.bottomAnchor, view.centerXAnchor, view.centerYAnchor, view.widthAnchor, view.heightAnchor. Anchor API ställer automatiskt in relatedBy = .equal och använder First Item/Second Item från Anchor, vilket minskar koden med 40% jämfört med klassisk NSLayoutConstraint.
import UIKit
class ConstraintViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let childView = UIView()
childView.backgroundColor = .systemBlue
childView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(childView)
NSLayoutConstraint.activate([
childView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 24),
childView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),
childView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16),
childView.heightAnchor.constraint(equalToConstant: 120),
childView.bottomAnchor.constraint(lessThanOrEqualTo: view.bottomAnchor, constant: -24)
])
}
}Koden placerar childView med marginaler från safeAreaLayoutGuide (top) och skärmkanter (leading/trailing). lessThanOrEqualTo för bottom garanterar att vyn inte överskrider den nedre gränsen. Anchor API kastar ett undantag i kompileringsfasen om ankare är inkompatibla (t.ex. leadingAnchor blandas med rightAnchor), vilket förhindrar runtime-fel. Apple rekommenderar Anchor API som standard för programmatisk Auto Layout från iOS 9.
Safe Area — det område på skärmen som inte täcks av systemelement: Dynamic Island, Notch, Status Bar, Home Indicator, rundade hörn. I iOS 11 ersatte Apple topLayoutGuide/bottomLayoutGuide med safeAreaLayoutGuide, som automatiskt anpassar sig till enhetens orientering och förekomsten av skärmutskärning. Layout Margins — standard inre marginaler för en vy (16pt på iOS, 20pt på iPadOS). För UILayoutGuide kan anpassade directionalLayoutMargins ställas in med hänsyn till RIGHT-TO-LEFT-lokalisering. Auto Layout tar automatiskt hänsyn till safe area vid användning av safeAreaLayoutGuide i ankare.
På enheter med Dynamic Island (iPhone 14 Pro och nyare) och Notch (iPhone X–13) utesluter Safe Area 44pt uppifrån i porträtt (59pt med Dynamic Island i aktivt tillstånd). Home Indicator lägger till 34pt nedifrån. För korrekt anpassning måste alla top-constraints kopplas till safeAreaLayoutGuide.topAnchor, inte till view.topAnchor. Bottom-constraints — till safeAreaLayoutGuide.bottomAnchor eller view.bottomAnchor med reserv för Home Indicator. Hos IT Sectr testar vi alla skärmar på simulatorer av iPhone SE (2022), iPhone 14 Pro Max och iPad Pro 12.9″ — tre enheter som täcker alla varianter av safe area.
De vanligaste felen vid arbete med Auto Layout: glömd translatesAutoresizingMaskIntoConstraints = false, motstridiga Required constraints (prioritet 1000), Ambiguous Layout (otillräckliga constraints för att bestämma position), felaktig Content Hugging Priority för UILabel med flerradig text och blandning av leading/trailing med left/right anchors. Xcode 15+ visar layoutproblem i Runtime Issue Navigator och erbjuder automatiska korrigeringar. För komplexa layouter, använd Debug View Hierarchy: gula etiketter indikerar tvetydig layout, röda — unsatisfiable.
| Fel | Orsak | Lösning |
|---|---|---|
| translatesAutoresizingMaskIntoConstraints = true | Auto Layout är inte aktiverat för vyn | Ställ in false för alla programmatiska vyer |
| Unsatisfiable Layout | Konflikt Required (1000) constraints | Sänk prioriteten för en till Default High (750) |
| Ambiguous Layout | Otillräckliga constraints för x/y/w/h | Lägg till saknad constraint eller kontrollera intrinsic size |
| Text trunkeras i UILabel | Content Hugging Priority lägre än konkurrent | Öka hugging priority till 252+ |
| Blandning av LTR/RTL-ankare | leadingAnchor med rightAnchor | Använd endast leading/trailing för RTL-stöd |
Vanliga frågor
Rambaserad layout anger fasta koordinater x, y, width, height för varje element. Auto Layout använder matematiska begränsningar (constraints) — relationer mellan element: «label.leading = button.trailing + 8». Rambaserad layout anpassar sig inte till skärmstorleken; Auto Layout räknar automatiskt om positioner vid rotation, Split View eller ändring av Dynamic Type.
UIStackView är optimalt för linjära layouter: rader, kolumner, formulär, parameterlistor. NSLayoutConstraint är nödvändigt för överlappande vyer, pixelprecision, anpassad bounds-animation och fall där utrymmesfördelningen är ojämn och inte täcks av UIStackView distribution. I praktiken löses 80% av layouterna med UIStackView, 20% med manuella constraints.
Content Hugging Priority (motstånd mot sträckning) — prioriteten som bestämmer hur mycket ett element motstår att öka sin storlek över Intrinsic Content Size. Standardvärde — 251. Om två element konkurrerar om ledigt utrymme stannar elementet med högre hugging priority kvar i sin storlek och det andra sträcks ut. Compression Resistance Priority (standard 749) fungerar analogt för komprimering.
Auto Layout anpassar sig automatiskt till Dynamic Type om constraints använder intrinsic content size för etiketter. När teckenstorleken ökar expanderar UILabel och flyttar närliggande element via constraints. UIStackView med distribution = fillProportionally omfördelar utrymmet proportionellt mot de nya intrinsic size. Safe Area och Layout Margins tar också hänsyn till tillgänglighetsinställningar.
Unsatisfiable Layout uppstår när två Required (priority = 1000) constraints motsäger varandra: till exempel view.leading = superview.leading + 16 och view.trailing = superview.leading + 200 med ett superview på 100pt bredd. Cassowary-algoritmen kan inte hitta en lösning och appen kraschar med NSConstraintException. Lösning — sänk prioriteten för en av de motstridiga constraints till Default High (750).
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också