안녕하세요, GraceKim입니다! 🍎
이번에 iOS App Dev Tutorials(2)로 Views에 대하여 공부하였는데, 이를 기록해보려고 합니다.
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입니다.
Swift의 열거형(enum)의 각 케이스에 할당된 원시 값(rawValue)를 나타내는 속성입니다.
enum Theme: String {
case bubblegum
case buttercup
// ... (다른 테마들)
case yellow
}
여기서 rawValue는 각 케이스의 원시 값으로 지정된 문자열을 나타냅니다. 예를 들어, Theme.bubblegum.rawValue는 "bubblegum"이 된다.
이러한 원시 값은 주로 열거형 케이스를 특정 데이터나 외부 시스템과 연결할 때 사용됩니다.
Models로 DailyScrum을 추가하였습니다. 후에, Extension을 통해 샘플 데이터를 확장하였습니다.
import Foundation
struct DailyScrum {
var title: String
var attendees: [String]
var lengthInMinutes: Int
var theme: Theme
}
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)
이렇게 정의해둔 후, 이와 같이 사용할 수 있습니다.
이제 위에서 만든 데이터로, 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 속성을 사용하도록 하는 것입니다.
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)
로 사용해도 됩니다.