[SwiftUI] Chapter 3_1. Composing Complex Interfaces

Ted·2023년 5월 11일
0

SwiftUI

목록 보기
4/5
post-thumbnail

Section1

Add a Category View

이번에는 카테고리를 만들어서 이를 View로 보여주는 화면 구성을 만들어보는 시간이다. 시작해보자.

일단 카테고리를 만든다.

import SwiftUI

struct CategoryHome: View {
    var body: some View {
        NavigationView {
            Text("Hello, World!")
                .navigationTitle("Featured")
        }
    }
}

struct CategoryHome_Previews: PreviewProvider {
    static var previews: some View {
        CategoryHome()
    }
}


다음과 같은 뷰가 형성이 된다.

Section 2

Create a Category List


다음은 landmarkData.json 파일로 부터 읽어온 데이터를 보여주려 하는 것이다.

다시 Landmark.swift 파일에 들어가서 Category를 더해준다.

var category: Category
    enum Category: String, CaseIterable, Codable {
        case lakes = "Lakes"
        case rivers = "Rivers"
        case mountains = "Mountains"
    }

다음은 ModelData.swift에서 categories를 붙여 넣어준다. dictionary 형태이며 category에서 이름은 key가 된다.

 var categories: [String: [Landmark]] {
        Dictionary(
            grouping: landmarks,
            by: { $0.category.rawValue }
        )
    }

@EnvironmentObject 형태로 CategoryHome.swift에 불러온다.

@EnvironmentObject var modelData: ModelData

그리고선 List뷰를 추가한다.

List {
	ForEach(modelData.categories.keys.sorted(), id: \.self) 
    { key in Text(key)}
}
.navigationTitle("Featured")

Section 3

Create a Category Row


랜드마크들을 우로 스크롤하게 하는 View 유형을 만들어본다.

CategoryRow.swift를 제작해보자.

import SwiftUI

struct CategoryRow: View {
    var categoryName: String
    var items: [Landmark]

    var body: some View {
        VStack(alignment: .leading) {
            Text(categoryName)
                .font(.headline)
                .padding(.leading, 15)
                .padding(.top, 5)

            ScrollView(.horizontal, showsIndicators: false) {
                HStack(alignment: .top, spacing: 0) {
                    ForEach(items) { landmark in
                        CategoryItem(landmark: landmark)
                    }
                }
            }
            .frame(height: 185)
        }
    }
}

struct CategoryRow_Previews: PreviewProvider {
    static var landmarks = ModelData().landmarks

    static var previews: some View {
        CategoryRow(
            categoryName: landmarks[0].category.rawValue,
            items: Array(landmarks.prefix(4))
        )
    }
}

우리는 이미 Landmark와 category에 대해서 설정을 해놨기 때문에 이를 그냥 View에 쌓으면 된다. 전체 View는 수직으로 작동하기 때문에 VStack이 가장 상위에 있고 다음은 ScrollView를 .horizontal로 설정해서 row scroll view로 만들어준다.

Section 4

Complete the Category View

이번엔 우리가 만들었던 CategoryRow하나를 이용해서 이제 여러개를 쌓아올려보는 것이다.

CategoryHome.swift에 다음과 같이 수정한다.

import SwiftUI

struct CategoryHome: View {
    @EnvironmentObject var modelData: ModelData

    var body: some View {
        NavigationView {
            List {
                ForEach(modelData.categories.keys.sorted(), id: \.self) { key in
                    CategoryRow(categoryName: key, items: modelData.categories[key]!)
                }
            }
            .navigationTitle("Featured")
        }
    }
}

struct CategoryHome_Previews: PreviewProvider {
    static var previews: some View {
        CategoryHome()
            .environmentObject(ModelData())
    }
}

일단 우리의 category는 Lakes, Mountains, Rivers이므로 이들을 ForEach문을 통해 sorted()된 형태로 나타내어준다.

저번에 배운 것처럼 id: .self 형태로 받아지게 된다.

그리고선 isFeatured에 대한 값을 넣어주기 위해서 Landmark.swift에 isFeatured를 추가한다.
그리고 ModelData.swift에도 다음 코드를 추가하여 feature를 설정할 수 있도록 만들어준다.

var features: [Landmark] {
        landmarks.filter { $0.isFeatured }
    }

CategoryHome.swift에선 다음 코드를 추가해 feature의 이미지가 Featured에 나타날 수 있도록 한다.

modelData.features[0].image
                    .resizable()
                    .scaledToFill()
                    .frame(height: 200)
                    .clipped()

그리곤 .listRowInsets(EdgeInsets())를 통해 layout이 좌우 끝까지 가도록 한다.

Section 5

Add Navigation Between Sections

이번에는 categoryHome에서 해당 랜드마크를 클릭 시에 기존 랜드마크의 상세 페이지로 향하는 navigation 연결을 해볼 것이다.

CategoryRow.swift에서 설정해놔야하기 때문에 다음의 코드를 ForEach(item) 하단에 넣어준다.

NavigationLink {
	LandmarkDetail(landmark: landmark)
                        } label: {
	CategoryItem(landmark: landmark)
}

다음엔 renderingMode()와 foregroundColor()를 추가해준다.

우리의 정말 오래전에 제작했었던 먼지 풀풀 풍기는 ContentView.swift를 다시 꺼내 Tab을 추가하자.

enum Tab {
        case featured
        case list
    }

그리곤 Tab을 @State private var 형태로 .featured로 만들어준다.

 @State private var selection: Tab = .featured

그리고는 TabView에서 이제 CategoryHome과 LandmarkList를 구분지어 navigate하기위해 다음과 같은 코드를 추가한다.

TabView(selection: $selection) {
            CategoryHome()
                .tabItem {
                    Label("Featured", systemImage: "star")
                }
                .tag(Tab.featured)

            LandmarkList()
                .tabItem {
                    Label("List", systemImage: "list.bullet")
                }
                .tag(Tab.list)
        }

Quiz



profile
iOS Developer

0개의 댓글