[SwiftUI] SwiftUI가 UI를 구현하는 방식

룰루날라·2022년 5월 18일
0
post-thumbnail

🔳 Views inside views

SwiftUI로 UI를 구현할 때의 패러다임, 즉 근본적인 사고방식과 틀은 ”뷰 안의 뷰”이다.
SwiftUI에서는 여러개의 작은 뷰를 더 큰 뷰에 넣어 UI를 구현한다.
여기서 이야기하는 작은 뷰, 큰 뷰는 무엇을 이야기하는 걸까?

🧱 Views like lego

SwiftUI의 뷰들은 레고와 비슷하다.

우리는 작은 레고 블럭을 조립해 의자, 자동차, 책상같은 레고 블럭을 만들고, 그 블럭들을 조합해 더 큰 블럭을 만든다.

예를 들어, 레고로 심슨의 집을 만들고 싶다면 레고 블럭을 조립해서 소파, TV 등의 블럭을 만들고 이 블럭들을 조합해 거실, 침실같은 방을, 그 방을 조합해 집을 완성한다.

SwiftUI에서의 View도 이와 같은 방식으로 구현된다.

뷰들을 조합해 더 큰 뷰를 만들고, 이 뷰들을 조합해서 또 더 큰 뷰를 만든다.
이 레고블럭들을 SwiftUI의 뷰들과 매치시켜보자면 다음과 같이 정리해볼 수 있을 것 이다.

블럭 조각

RoundedRectangle, Circle, Text, Button 등의 UI Element

소파, TV, 우체통 블럭

HStack, VStack, ZStack, LazyVGrid 등의 Container(Combiner View라고도 부른다)에 블럭 조각을 넣어 더 큰 뷰를 만든다.

거실, 집 블럭

위에서 만든 Element들과 Container들을 조합해서 더 큰 뷰를 만든다.

(+) 블럭 비닐 백

우리가 레고를 조립하기 위해 박스를 뜯어보면 아래 사진처럼 레고 블럭들이 비닐 백에 나눠 담겨있다.

조립하기 쉽도록 부품별로 필요한 레고블럭을 나눠서 담아 놓은 것이다.
비닐 백 하나는 날개 부분, 다른 비닐백은 조종석 부분 등으로 작은 블럭을 만들기 위한 레고 블럭들이 나뉘어 담겨 있다.

SwiftUI에서도 작은 뷰들로 큰 뷰를 만들 때, 작은 뷰들을 백에 담아서 Combiner View에게 전달한다.
‘백에 담는다’는 표현이 모호할 수 있는데 쉽게 말하면 레고 블럭들, 즉 여러 UI Element를 나열해 하나의 블럭으로 만든다는 것이다.
다음과 같이 말이다.

ZStack {
    RoundedRectangle(cornerRadius: 20)
        .foregroundColor(.white)
    RoundedRectangle(cornerRadius: 20)
        .strokeBorder(lineWidth: 3)
        .foregroundColor(.yellow)
    Text(content)
        .font(.largeTitle)
}

이렇게 작은 뷰들을 하나의 블럭으로 만드는 것에는 ViewBuilder와 ForEach 등이 있는데, 이 녀석들에 대해서는 다음에 더 알아보도록 하자.

👩‍💻 코드로 확인해보기

지금까지 이야기했던 내용을 실제로 View 코드를 짜는 걸 보면서 정리해보자.

코드와 프리뷰를 함께 보면, 아래와 같은 모습을 확인할 수 있다.

  • RoundedRectangle, Text를 나열한 뒤, ZStack에 담아준다.
  • 여러개의 CardView를 HStack 또는 LazyVGrid에 담아준다.
  • ForEach를 사용해 데이터의 수 만큼 CardView를 반복해서 만들어준다.
  • LazyVGrid를 ScrollView에 담아준다.
  • 여러개의 Button을 HStack에 담아준다.

공부할수록 블럭을 가지고 조립하면서 노는 것 같아서 정말 재미있다😎


Gif의 코드는 여기에~
struct ContentView: View {
    let emojis: [String] = ["✈️", "🚌", "🚟", "🛵", "⛵️", "🚡", "🚗", "🛻", "🚂", "🛳", "🚉", "🚀", "🛶", "🚁", "🚜", "🚁"]
    @State var emojiCount = 4
    
    var body: some View {
        VStack {
            ScrollView {
                LazyVGrid(columns: [GridItem(), GridItem()]) {
                    ForEach(emojis, id:\.self) { emoji in
                        CardView(content: emoji)
                            .aspectRatio(2/3, contentMode: .fit)
                    }
                }
            }
            Spacer(minLength: 30)
            HStack {
                button
                    .font(.largeTitle)
                button
                    .font(.largeTitle)
                button
                    .font(.largeTitle)
            }
        }
    }
    
    var button: some View {
        Button {
             emojiCount += 1
        } label: {
            Image(systemName: "plus.circle")
        }

    }
}

struct CardView: View {
    var content: String
    
    var body: some View {
        ZStack {
            RoundedRectangle(cornerRadius: 20)
                .strokeBorder(lineWidth: 3)
                .foregroundColor(.yellow)
            Text(content)
                .font(.largeTitle)
        }
    }
}




profile
즐거운 인생 (~-_-)~ ~(-_-~)

0개의 댓글