안녕하세요, GraceKim입니다! 🍎

이번에 iOS App Dev Tutorials(2)로 Views에 대하여 공부하였는데, 이를 기록해보려고 합니다.


Creating a card View

Create a color theme

Theme.swift

import SwiftUI


enum Theme: String {
    case bubblegum
    case buttercup
    case indigo
    case lavender
    case magenta
    case navy
    case orange
    case oxblood
    case periwinkle
    case poppy
    case purple
    case seafoam
    case sky
    case tan
    case teal
    case yellow
    
    var accentColor: Color {
        switch self {
        case .bubblegum, .buttercup, .lavender, .orange, .periwinkle, .poppy, .seafoam, .sky, .tan, .teal, .yellow: return .black
        case .indigo, .magenta, .navy, .oxblood, .purple: return .white
        }
    }
    var mainColor: Color {
        Color(rawValue)
    }
}

열거형을 통해 Color의 케이스를 추가하였습니다. 이때 Assets에 미리 해당 색상들을 모두 넣어주었습니다.(넣지 않으면 색상을 불러오지 못하니 주의)

여기서 핵심은 rawValue입니다.

rawValue와 열거형

Swift의 열거형(enum)의 각 케이스에 할당된 원시 값(rawValue)를 나타내는 속성입니다.

enum Theme: String {
    case bubblegum
    case buttercup
    // ... (다른 테마들)
    case yellow
}

여기서 rawValue는 각 케이스의 원시 값으로 지정된 문자열을 나타냅니다. 예를 들어, Theme.bubblegum.rawValue"bubblegum"이 된다.

이러한 원시 값은 주로 열거형 케이스를 특정 데이터나 외부 시스템과 연결할 때 사용됩니다.

Create a daily scrum model

Models로 DailyScrum을 추가하였습니다. 후에, Extension을 통해 샘플 데이터를 확장하였습니다.

import Foundation


struct DailyScrum {
    var title: String
    var attendees: [String]
    var lengthInMinutes: Int
    var theme: Theme
}

Create the card view

card view의 style을 만들었습니다. scrum.attendees.count를 통해 scrum의 attendees의 배열 안 개수를 리턴하였습니다.

import SwiftUI


struct CardView: View {
    let scrum: DailyScrum
    var body: some View {
        VStack(alignment: .leading) {
            Text(scrum.title)
                .font(.headline)
            Spacer()
            HStack {
                Label("\(scrum.attendees.count)", systemImage: "person.3")
                Spacer()
                Label("\(scrum.lengthInMinutes)", systemImage: "clock")
                    .padding(.trailing, 20)
            }
            .font(.caption)
        }
        .padding()
        .foregroundColor(scrum.theme.accentColor)
    }
}


struct CardView_Previews: PreviewProvider {
    static var scrum = DailyScrum.sampleData[0]
    static var previews: some View {
        CardView(scrum: scrum)
            .background(scrum.theme.mainColor)
            .previewLayout(.fixed(width: 400, height: 60))
    }
}

이때, 재사용되는 레이블 스타일이 있는데, 동일한 스타일을 재사용 휫수가 많을 경우에 프로토콜을 통해서 재사용할 수 있습니다.

import SwiftUI


struct TrailingIconLabelStyle: LabelStyle {
    func makeBody(configuration: Configuration) -> some View {
        HStack {
            configuration.title
            configuration.icon
        }
    }
}


extension LabelStyle where Self == TrailingIconLabelStyle {
    static var trailingIcon: Self { Self() }
}
  • LabelStyle을 채택하는 TrailingIconLabelStyle이라는 프로토콜을 정의하였습니다. 이때 makebody 함수는 해당 스타일이 적용될 때 Label의 외관을 정의할 수 있습니다.

  • trailingIcon 이라는 타입 프로퍼티를 추가하여 TrailingIconLabelStyle을 반환할 수 있습니다.

Text("Hello, World!")
    .labelStyle(TrailingIconLabelStyle.trailingIcon)

이렇게 정의해둔 후, 이와 같이 사용할 수 있습니다.

Displaying data in a list

Display a list of daily scrums

이제 위에서 만든 데이터로, scrumList를 만들기 위해 다음과 같이 만들었습니다.

import SwiftUI


struct ScrumsView: View {
    let scrums: [DailyScrum]
    
    var body: some View {
        List(scrums, id: \.title) { scrum in
            CardView(scrum: scrum)
                .listRowBackground(scrum.theme.mainColor)
        }
    }
}


struct ScrumsView_Previews: PreviewProvider {
    static var previews: some View {
        ScrumsView(scrums: DailyScrum.sampleData)
    }
}

이때 List에 id: \.title부분이 있는데, 이는 Swift의 List 뷰가 목록 내의 각 항목에 대한 고유 식별자가 필요하기 때문입니다. 이 식별자는 SwiftUI가 목록을 효율적으로 관리하고 내용을 업데이트하는 데 사용됩니다.

\.title은 각 DailyScrum 객체의 title 속성을 가리키는 키 경로인데, \.title을 사용함으로써 SwiftUI에게 목록 내 각 DailyScrum에 대한 식별자로 title 속성을 사용하도록 하는 것입니다.

Make scrums identifiable

import Foundation


struct DailyScrum: Identifiable {
    let id: UUID
    var title: String
    var attendees: [String]
    var lengthInMinutes: Int
    var theme: Theme
    
    init(id: UUID = UUID(), title: String, attendees: [String], lengthInMinutes: Int, theme: Theme) {
        self.id = id
        self.title = title
        self.attendees = attendees
        self.lengthInMinutes = lengthInMinutes
        self.theme = theme
    }
}


extension DailyScrum {
    static var sampleData: [DailyScrum] {
        [
            DailyScrum(title: "Design", attendees: ["Cathy", "Daisy", "Simon", "Jonathan"], lengthInMinutes: 10, theme: .yellow),
            DailyScrum(title: "App Dev", attendees: ["Katie", "Gray", "Euna", "Luis", "Darla"], lengthInMinutes: 5, theme: .orange),
            DailyScrum(title: "Web Dev", attendees: ["Chella", "Chris", "Christina", "Eden", "Karla", "Lindsey", "Aga", "Chad", "Jenn", "Sarah"], lengthInMinutes: 5, theme: .poppy)
        ]
    }
}

이 코드에서 UUID를 추가하고, init으로 초기화를 시켜주었습니다. 그 이유는 다음과 같습니다.

  • SwiftUI에서는 Identifiable 프로토콜을 따르는 형식은 각 인스턴스에 대해 고유한 식별자가 필요한데, 이는 데이터를 식별하여 목록 내에서 항목을 구분하고 업데이트할 때 사용됩니다. UUID는 중복되지 않는 고유한 값을 생성하는 데 사용되며, 이를 통해 각 DailyScrum 인스턴스는 고유한 식별자를 가지게 됩니다.

  • 또한, 초기화 함수(init)를 추가함으로써 객체를 편리하게 생성할 수 있습니다. 그리고 사용자는 UUID를 직접 생성하지 않아도 됩니다. 만약 외부에서 UUID를 제공하지 않으면 자동으로 새 UUID가 생성됩니다.

따라서 위에 List에 id: \.title 부분을 지우고, List(scrums)로 사용해도 됩니다.

profile
T자형 개발자가 되고 싶은 GraceKim입니다 / 구름톤 유니브 Leader

0개의 댓글

Powered by GraphCDN, the GraphQL CDN