SwiftUI

SwiftUI | SwiftData Tutorials - List / NavigationStack / DatePicker

ziziDev 2024. 8. 8. 00:03
반응형

SwiftData Tutorials

 

List로 통해 각 친구들이름이 표시되는걸 볼 수 있습니다

그리고 Spacer()공간을 두고 우측에 출생일을 표기하고 있습니다

 

 

NavigationStack.navigationTitle을 통해 화면 상단에

생일을 표기합니다

 

새로운 친구와 날짜를 추가하기 위해 newName / newDate를 선언합니다

그리고 화면 하단에 친구 항목 UI를 고정하는데 

.safeAreaInset(edge:.bottom)메서드를 사용합니다

이 메서드는 상단이나 하단에 고정할 수 있습니다

 

import SwiftUI

struct BirthdayView: View {
    @State private var friends: [Friend] = [
        Friend(name: "Elton Lin", birthday: .now),
        Friend(name: "Jenny Court", birthday: Date(timeIntervalSince1970: 0))
    ]
    
    @State private var newName = ""
    @State private var newDate = Date.now
    
    var body: some View {
        NavigationStack {
            List(friends, id: \.name) { friend in
                HStack {
                    Text(friend.name)
                    Spacer()
                    Text(friend.birthday, format: .dateTime.month(.wide).day().year())
                }
            }
            .navigationTitle("Birthday")
            .safeAreaInset(edge: .bottom) {
                VStack(alignment: .center, spacing: 20, content: {
                    Text("New Birthday")
                        .font(.headline)
                    
//                    DatePicker(<#T##titleKey: LocalizedStringKey##LocalizedStringKey#>, selection: <#T##Binding<Date>#>, in: <#T##ClosedRange<Date>#>, displayedComponents: <#T##DatePicker<Text>.Components#>)
                    DatePicker(selection: $newDate, in: Date.distantPast...Date.now, displayedComponents: .date) {
                        TextField("Name", text: $newName)
                            .textFieldStyle(.roundedBorder)
                    }
                    
                    Button("Save") {
                        let newFriend = Friend(name: newName, birthday: newDate)
                        friends.append(newFriend)
                    }
                    .bold()
                })
                .padding()
                .background(.bar) //툴바와 같은 배경 스타일링
            }
        }
    }
}

#Preview {
    BirthdayView()
}

 

 

import SwiftUI
import SwiftData

struct BirthdayView: View {
    //State -> Query모델 객체가 변경되면 자동으로 업데이트됨
    //데이터를 쉽게 가져올 수 있도록 하기 위해서 Query 키워드 사용
    //자동으로 업데이트 상태 유지하는 역할
    //birthday 속성을 기준으로 정렬해서 가져옴
    @Query(sort: \Friend.birthday) private var friends: [Friend]
    //@Environment SwiftUI에서 환경 변수를 사용해서 SwiftData 모델 컨텍스트를 가져오는것 의미
    //\.modelContext 키 경로로 현재 환경에서 모든 컨텍스트를 참조할 수 있음
    //사용시 데이터 베이스 작업인 삭제/삽입/업데이트를 수행할 수 있는 모델 컨텍스트를 가져올 수 있음
    @Environment(\.modelContext) private var context
    
    @State private var newName = ""
    @State private var newDate = Date.now //2000년 1월 4일 0:00:00 UTC
    
    var body: some View {
        NavigationStack {
            //SwiftData는 데이터와 별도로 고유한 ID를 제공하기 때문에 List에서 아규먼트 중 id를 제거해도됨
            List(friends) { friend in
                HStack {
                    
                    if friend.isBirthdayToday {
                        Image(systemName: "birthday.cake")
                    }
                    
                    Text(friend.name)
                        .bold(friend.isBirthdayToday)
                    Spacer()
                    Text(friend.birthday, format: .dateTime.month(.wide).day().year())
                }
            }
            .navigationTitle("Birthday")
            .safeAreaInset(edge: .bottom) {
                VStack(alignment: .center, spacing: 20, content: {
                    Text("New Birthday")
                        .font(.headline)
                    
//                    DatePicker(<#T##titleKey: LocalizedStringKey##LocalizedStringKey#>, selection: <#T##Binding<Date>#>, in: <#T##ClosedRange<Date>#>, displayedComponents: <#T##DatePicker<Text>.Components#>)
                    DatePicker(selection: $newDate, in: Date.distantPast...Date.now, displayedComponents: .date) {
                        TextField("Name", text: $newName)
                            .textFieldStyle(.roundedBorder)
                    }
                    
                    Button("Save") {
                        let newFriend = Friend(name: newName, birthday: newDate)
                        context.insert(newFriend)
                        
                        newName = ""
                        newDate = .now
                    }
                    .bold()
                })
                .padding()
                .background(.bar) //툴바와 같은 배경 스타일링
            }
//            .task {
//                context.insert(Friend(name: "Elton Lin", birthday: .now))
//                context.insert(Friend(name: "Jenny Court", birthday: Date(timeIntervalSince1970: 0)))
//            }
        }
    }
}

#Preview {
    BirthdayView()
        //미리보기는 새로 고칠 때마다 동일한 초기상태에서 시작하기 때문에
        //modelContainer에 inMemory ture로 설정해서 앱이 메모리에 있는 동안 저장되도록 설정
        .modelContainer(for: Friend.self, inMemory: true)
}
import Foundation
//종료해도 사라지지 않도록 하는 도구를 제공
import SwiftData

//실행 간에도 뷰 계층 외부의 앱 상태를 나타내는데 복잡한 application을 조립하기 위한 또 다른 강력한 도구가 생김
@Model // 매크로 주석 추가
//class 모델로 변환해야함 - 참조 타입으로 여러 곳에서 참조할 수 있고 데이터 일관성 유지하는데 유리함
//값 타입은 복사될 때 마다 인스턴스가 새로 생성되기 때문에 데이터 일관성 유지와 메모리 효율성 면에서 클래스보다 적합하지 않음
//객체를 고유하게 식별해야하기 때문에 클래스는 고유한 식별자를 가질 수 있음
class Friend {
    let name: String
    let birthday: Date
    
    init(name: String, birthday: Date) {
        self.name = name
        self.birthday = birthday
    }
    
    var isBirthdayToday: Bool {
        Calendar.current.isDateInToday(birthday)
    }
}

반응형