Grunderna i Layout-protokollet
Implementera sizeThatFits och placeSubviews.
Grunderna i Layout-protokollet är en gratis lektion i Swift Academy på CoddyKit. Detta är lektion 1 av 4. Du kan läsa vilka 3 lektioner som helst i den här lärvägen kostnadsfritt i sin helhet – därefter låser CoddyKit PRO upp alla lektioner, plus praktisk övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Den ingår i lärvägen för Swift Academy, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Swift Academy innehåller totalt 4 lektioner.
Varför en anpassad layout?
SwiftUI levereras med HStack, VStack och ZStack, men ibland behövs arrangeringslogik som de inte kan uttrycka – radialmenyer, flödeslayouter och masonry-rutnät.
Protokollet Layout gör det möjligt att skriva sådan logik och samtidigt komponera med vanliga SwiftUI-vyer.
Layout-protokollet
Layout kräver två metoder: sizeThatFits (hur stor ska jag vara?) och placeSubviews (var ska varje barn placeras?).
Man konformerar en värdetyp och använder den som vilken inbyggd stack som helst.
struct MyLayout: Layout {
func sizeThatFits(proposal: ProposedViewSize,
subviews: Subviews,
cache: inout ()) -> CGSize { .zero }
func placeSubviews(in bounds: CGRect,
proposal: ProposedViewSize,
subviews: Subviews,
cache: inout ()) { }
}Använda en anpassad layout
Ett värde av typen Layout fungerar som en container. Barnvyer skickas in i dess trailing closure, precis som i en stack.
var body: some View {
MyLayout {
Text("One")
Text("Two")
Text("Three")
}
}ProposedViewSize
Föräldern föreslår en storlek för layouten via ProposedViewSize. Dess width och height är optionals: nil betyder "ospecificerat, välj idealstorlek".
Specialvärdena .zero, .infinity och .unspecified undersöker minsta, största respektive idealiska storlek.
func sizeThatFits(proposal: ProposedViewSize,
subviews: Subviews,
cache: inout ()) -> CGSize {
let width = proposal.width ?? 0
return CGSize(width: width, height: 44)
}sizeThatFits i detalj
sizeThatFits returnerar den storlek layouten vill ha utifrån ett förslag. SwiftUI kan anropa den flera gånger med olika förslag för att förstå hur flexibel layouten är.
func sizeThatFits(proposal: ProposedViewSize,
subviews: Subviews,
cache: inout ()) -> CGSize {
// Sum child ideal sizes for a simple horizontal stack
let sizes = subviews.map { $0.sizeThatFits(.unspecified) }
let w = sizes.reduce(0) { $0 + $1.width }
let h = sizes.map(\.height).max() ?? 0
return CGSize(width: w, height: h)
}Samlingen Subviews
Subviews är en samling proxyer för varje barn. Varje proxy besvarar sizeThatFits och tillhandahåller layoutprioriteter och anpassade värden.
De riktiga vyerna är aldrig synliga – endast dessa mätproxyer används.
for subview in subviews {
let size = subview.sizeThatFits(.unspecified)
print(size)
}placeSubviews
placeSubviews tilldelar varje barn en position inom rektangeln bounds som layouten har fått.
Anropa place(at:anchor:proposal:) på varje subview-proxy.
func placeSubviews(in bounds: CGRect,
proposal: ProposedViewSize,
subviews: Subviews,
cache: inout ()) {
var x = bounds.minX
for subview in subviews {
let size = subview.sizeThatFits(.unspecified)
subview.place(at: CGPoint(x: x, y: bounds.midY),
anchor: .leading,
proposal: .unspecified)
x += size.width
}
}Ankare vid placering
Parametern anchor anger vilken punkt på barnet som ska hamna på den angivna positionen. .topLeading placerar barnet med det övre vänstra hörnet; .center centrerar barnet på punkten.
subview.place(at: CGPoint(x: 0, y: 0),
anchor: .topLeading,
proposal: .unspecified)Bounds börjar inte alltid vid origo
Rektangeln bounds börjar kanske inte vid (0,0). Placera alltid relativt till bounds.minX och bounds.minY, aldrig relativt till absolut noll.
let startX = bounds.minX // not 0
let startY = bounds.minYEn minimal layout med jämnt avstånd
När allt sätts ihop får vi här en layout som placerar barn från vänster till höger utan mellanrum. De två metoderna är konsekventa: den rapporterade storleken stämmer överens med placeringen.
struct SimpleHStack: Layout {
func sizeThatFits(proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) -> CGSize {
let sizes = subviews.map { $0.sizeThatFits(.unspecified) }
return CGSize(width: sizes.reduce(0){ $0 + $1.width },
height: sizes.map(\.height).max() ?? 0)
}
func placeSubviews(in bounds: CGRect, proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) {
var x = bounds.minX
for s in subviews {
let size = s.sizeThatFits(.unspecified)
s.place(at: CGPoint(x: x, y: bounds.minY), anchor: .topLeading, proposal: .unspecified)
x += size.width
}
}
}Konsistensen är ert ansvar
SwiftUI litar på att de två metoderna stämmer överens. Om placeSubviews använder mer utrymme än vad sizeThatFits rapporterade kan barn beskäras eller överlappa varandra.
Håll geometriberäkningarna gemensamma för båda metoderna.
Snabbtest: layoutgrunder
Testa förståelsen av Layout-protokollet.
Sammanfattning: grunderna i Layout-protokollet
Protokollet Layout omvandlar anpassad arrangeringslogik till en återanvändbar container. sizeThatFits rapporterar layoutens storlek för ett ProposedViewSize, och placeSubviews placerar varje barnproxy inom bounds med hjälp av place(at:anchor:proposal:).
Förslag innehåller valfria dimensioner, bounds kan vara förskjutna från origo, och de två metoderna måste förbli geometriskt konsekventa. Nästa steg är att mäta subviews mer ingående.
Lär dig Swift med en AI-lärare – gratis
Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.
- Kurser
- 122
- Lektioner
- 409
Vanliga frågor
Är lektionen ”Grunderna i Layout-protokollet” gratis?
Ja – du kan läsa vilka 3 lektioner som helst i lärvägen Swift Academy, inklusive ”Grunderna i Layout-protokollet”, kostnadsfritt i sin helhet här på webben. Därefter låser CoddyKit PRO upp alla lektioner, plus interaktiv övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Kursen i Swift Academy innehåller totalt 4 lektioner.
Vad lär jag mig i ”Grunderna i Layout-protokollet”?
Implementera sizeThatFits och placeSubviews. Ni övar på Swift Academy med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.
Behöver jag någon erfarenhet för att börja lära mig Swift Academy?
Du behöver inga förkunskaper. Utbildningen i Swift Academy på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 1 av 4.
Hur lång tid tar lektionen ”Grunderna i Layout-protokollet”?
De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.
Kan jag skriva och köra kod i den här Swift Academy-lektionen?
Ja. Varje Swift Academy-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.
Alla lektioner i den här kursen
- Grunderna i Layout-protokollet
- Mäta subviews
- Bygga en flow layout
- Layout-cache och prestanda