Layout 프로토콜 기초
sizeThatFits와 placeSubviews를 구현합니다.
Layout 프로토콜 기초은(는) CoddyKit의 무료 Swift Academy 강의입니다. 이것은 4개 중 1번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Swift Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Swift Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
사용자 지정 레이아웃이 필요한 이유
SwiftUI에는 HStack, VStack, ZStack이 기본 제공되지만, 방사형 메뉴나 흐름 레이아웃, 석조식 격자처럼 이러한 구성 요소로 표현할 수 없는 배치 로직이 필요할 때가 있습니다.
레이아웃 프로토콜을 사용하면 일반적인 SwiftUI 뷰와 계속 조합하면서 이러한 로직을 작성할 수 있습니다.
레이아웃 프로토콜
Layout에는 두 메서드가 필요합니다. sizeThatFits는 레이아웃의 크기를 결정하고, placeSubviews는 각 자식 뷰의 위치를 결정합니다.
값 타입에 적합성을 추가하면 기본 제공 스택처럼 사용할 수 있습니다.
struct MyLayout: Layout {
func sizeThatFits(proposal: ProposedViewSize,
subviews: Subviews,
cache: inout ()) -> CGSize { .zero }
func placeSubviews(in bounds: CGRect,
proposal: ProposedViewSize,
subviews: Subviews,
cache: inout ()) { }
}사용자 지정 레이아웃 사용하기
Layout 값은 컨테이너 역할을 합니다. 스택과 마찬가지로 후행 클로저에 자식 뷰를 전달합니다.
var body: some View {
MyLayout {
Text("One")
Text("Two")
Text("Three")
}
}ProposedViewSize
부모는 ProposedViewSize를 통해 레이아웃에 크기를 제안합니다. 이 값의 width와 height는 선택 사항이며, nil은 "지정되지 않았으므로 원하는 크기를 선택하라"는 뜻입니다.
.zero, .infinity, .unspecified라는 특수 값은 각각 최소 크기, 최대 크기, 이상적인 크기를 확인합니다.
func sizeThatFits(proposal: ProposedViewSize,
subviews: Subviews,
cache: inout ()) -> CGSize {
let width = proposal.width ?? 0
return CGSize(width: width, height: 44)
}sizeThatFits 자세히 알아보기
sizeThatFits는 제안이 주어졌을 때 레이아웃이 원하는 크기를 반환합니다. SwiftUI는 레이아웃의 유연성을 파악하기 위해 서로 다른 제안으로 이 메서드를 여러 번 호출할 수 있습니다.
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)
}하위 뷰 컬렉션
Subviews는 각 자식 뷰를 대신하는 프록시의 컬렉션입니다. 각 프록시는 sizeThatFits에 응답하고 레이아웃 우선순위와 사용자 지정 값을 제공합니다.
실제 뷰를 직접 볼 수는 없고 이러한 측정 프록시만 확인할 수 있습니다.
for subview in subviews {
let size = subview.sizeThatFits(.unspecified)
print(size)
}placeSubviews
placeSubviews는 전달받은 bounds 사각형 안에서 각 자식의 위치를 지정합니다.
각 하위 뷰 프록시에서 place(at:anchor:proposal:)을 호출하십시오.
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
}
}배치할 때 앵커 사용하기
anchor 매개변수는 자식 뷰의 어느 지점을 지정한 위치에 놓을지 나타냅니다. .topLeading은 왼쪽 위 모서리를 기준으로 배치하고, .center는 자식 뷰의 중심을 해당 위치에 맞춥니다.
subview.place(at: CGPoint(x: 0, y: 0),
anchor: .topLeading,
proposal: .unspecified)Bounds가 항상 원점에 있는 것은 아닙니다
bounds 사각형은 (0,0)에서 시작하지 않을 수 있습니다. 항상 절대 좌표 0이 아니라 bounds.minX와 bounds.minY를 기준으로 위치를 지정하십시오.
let startX = bounds.minX // not 0
let startY = bounds.minY간격을 동일하게 두는 최소 레이아웃
이제 지금까지의 내용을 결합해 보겠습니다. 다음은 자식 뷰를 간격 없이 왼쪽에서 오른쪽으로 배치하는 레이아웃입니다. 두 메서드는 일관되게 동작하며, 보고된 크기와 실제 배치가 일치합니다.
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
}
}
}일관성은 개발자의 책임입니다
SwiftUI는 두 메서드가 일치한다고 가정합니다. placeSubviews가 sizeThatFits에서 보고한 크기보다 더 많은 공간을 사용하면 자식 뷰가 잘리거나 겹칠 수 있습니다.
두 메서드에서 기하 계산을 공유하여 일관성을 유지하십시오.
빠른 확인: 레이아웃 기초
레이아웃 프로토콜에 대한 이해도를 확인해 보십시오.
복습: 레이아웃 프로토콜 기초
Layout 프로토콜은 사용자 지정 배치 로직을 재사용 가능한 컨테이너로 바꿉니다. sizeThatFits는 ProposedViewSize에 대한 레이아웃 크기를 보고하고, placeSubviews는 place(at:anchor:proposal:)을 사용해 bounds 안에 각 자식 프록시를 배치합니다.
제안에는 선택적인 치수가 포함되고, bounds는 원점에서 이동되어 있을 수 있으며, 두 메서드는 기하학적으로 일관되어야 합니다. 다음에는 하위 뷰를 자세히 측정합니다.
자주 묻는 질문
“Layout 프로토콜 기초” 강의는 무료인가요?
네 — “Layout 프로토콜 기초” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Swift Academy 강의 전체를 잠금 해제할 수 있습니다. Swift Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“Layout 프로토콜 기초”에서 뭘 배우나요?
sizeThatFits와 placeSubviews를 구현합니다. 브라우저에서 직접 실행하는 실습 코드로 Swift Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
Swift Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 Swift Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 1번째 강의입니다.
“Layout 프로토콜 기초” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 Swift Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 Swift Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- Layout 프로토콜 기초
- 하위 뷰 측정하기
- 플로 레이아웃 만들기
- 레이아웃 캐시와 성능