티스토리 뷰
오늘은 DatePicker와 DateFormatter를 활용하여 TaskEditor를 만들어보자!
주요 기능
- task 추가 기능
- task 삭제 기능
- task 수정 기능
- DatePicker를 사용하여 날짜 수정
UI
DatePicker
DatePicker란, 날짜를 선택하기 위한 컨트롤이다. 애플 공식 문서에 찾아보면 다양한 디자인, 사용방법을 예시로 들어 친절하게 알려준다!
공식문서 링크를 첨부해 둘 테니 참고하시길! - 링크
let dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateStyle = .short
formatter.timeStyle = .none
return formatter
}()
DatePicker에서 제공하는 DateFormatter를 사용해 보았다.
구조체 형성
struct TaskItem: Identifiable {
var id = UUID()
var title: String
var date: Date
var state: String
}
task안에 들어간 정보들을 관리하기 위해 구조체를 형성하여 관리하였다.
+ 버튼을 누를 때마다 task가 생겨나야 하기 때문에 고유 식별 아이디를 추가해 주었고,
task안에 들어가는 제목, 날짜, 상태를 구조체에 포함시켰다.
ContentView
struct ContentView: View {
@State private var tasks = [TaskItem]()
@State private var date = Date()
@State private var isEditForm = false
var body: some View {
NavigationView {
VStack {
List {
ForEach($tasks) { $task in
VStack(alignment: .leading) {
if isEditForm {
EditView(task: $task)
} else {
TaskView(task: task)
}
}
}
.onDelete(perform: deleteTasks)
}
}
.navigationTitle("Tasks")
.navigationBarItems(trailing:
Button(action: {
isEditForm.toggle()
}, label: {
Text(isEditForm ? "Done" : "Edit")
.font(.title2)
}))
.navigationBarItems(trailing:
Button(action: {
addItem()
}, label: {
Image(systemName: "plus")
.font(.title2)
}).disabled(isEditForm)
)
}
}
func addItem() {
let newTask = TaskItem(title: "New Task", date: Date(), state: "Not started")
tasks.append(newTask)
}
func deleteTasks(at offsets: IndexSet) {
tasks.remove(atOffsets: offsets)
}
}
ContentView에는 테스크의 추가, 삭제 함수도 포함되어 있으며 전반적인 UI에 대한 구조가 담겨 있다.
navigationLink를 사용하기가 싫어서 edit버튼을 눌렀을 때 리스트 안에 컴포넌트를 갈아 끼우는 방식으로 구현하였다.
- @State private var tasks = [TaskItem]() : TaskItem의 배열을 state로 관리
- @State private var isEditForm = false : isEditForm을 state로 사용하여 edit모드를 관리
- Edit 버튼을 누를 때 isEditForm 값이 변경되어 List안의 항목을 전환해야 함.
- @State private var date = Date() : 현재 날짜를 표시
NavigationView를 사용하지 않고 VStack에 HStack을 추가하여 버튼들을 넣어주고 그 밑에 VStack에 리스트를 추가하여 구현을 시도해 보았지만 원하는 UI대로 잘 나오지 않아서 설계를 한번 갈아엎었었다.
NavigationView 안에 VStack을 넣고 그 안에 List를 넣어 Foreach문으로 isEditForm상태(true/false)에 따라 다른 뷰를 보여주도록 하였으며, 위에 위치해 있는 버튼들은 NavigationBarItems으로 구현해 주었다.
** 아 그리고 NavigationView는 항상 최상단에 위치해야 한다..
TaskView
struct TaskView: View {
let task: TaskItem
var body: some View {
VStack(alignment: .leading) {
Text(task.title)
.font(.headline)
Text("Due date: \(task.date, formatter: dateFormatter)") // 태스크 날짜
.font(.subheadline)
Text("Status: \(task.state)") // 태스크 상태
.font(.caption)
}
}
}
TaskView는 수정된 task들을 리스트에 보여줄 때 사용된다.
EditView
struct EditView: View {
@Binding var task: TaskItem
var body: some View {
VStack(alignment: .leading) {
TextField("New Task", text: $task.title)
.font(.subheadline)
DatePicker(
selection: $task.date, displayedComponents: .date) {
Text("Due Date")
}
Picker("Status", selection: $task.state) {
Text("Not started").tag("Not started")
Text("In progress").tag("In progress")
Text("Complete").tag("Complete")
}
.pickerStyle(SegmentedPickerStyle())
}
}
}
EditView는 생성된 task들에 대해 수정할 수 있는 기능이며 done 버튼을 누르면 수정 사항이 저장된다.
Edit 버튼을 누르면 위와 같은 뷰가 뜨도록 스타일에 맞게 지정해 주었다.
과제를 하다가 찾아보니 DateFormatter에도 휠디자인, 그래픽 디자인, 오늘 시점을 기준으로 미래 날짜만 선택되게 하는 기능, 오늘 시점을 기준으로 과거 날짜만 선택되게 하는 기능 등등 다양한 기능들과 디자인이 있어서 잘 활용해 볼 수 있을 거 같다!
느낀 점
엄청 어려울 줄 알았던 이번 과제는 생각보다 쉽게 느껴졌다. DatePicker과 Formatter 사용에 낯설어서 조금 겁먹었는데, 공식문서를 보고 블로그를 참고하니 핀터레스트 과제보다 훨씬 간단하게 구현할 수 있었던 거 같다!!
이번 과제를 하면서도 느낀 건 항상 구현전에 설계를 제대로 하고 가야 삽질하는 시간이 줄어든다는 것이다..
어떤 구조로 어떻게 설계할 것인지를 조금 더 깊게 생각해 봤으면 버튼을 HStack으로 구성하지 않고 바로 navigationBarItems으로 구현했을 거 같은데 이 시간만 줄였어도 정말 금방 구현했을 과제였다 . .
앞으로 꼭 설계를 탄탄하게 다지고 구현을 시작하자.. 오래 걸리더라도..
'iOS > SwiftUI' 카테고리의 다른 글
[iOS/SwiftUI] SwiftUI 에서 LifeCycle 관리 (0) | 2024.04.05 |
---|---|
[iOS/SwiftUI] Preview Crashed 해결방법 (0) | 2024.03.30 |
[iOS/SwiftUI] LazyVGrid를 활용하여 뷰 만들기 (1) | 2024.02.25 |
[iOS/SwiftUI] List를 활용한 TodoList 만들기 (1) | 2024.02.07 |
[iOS/SwiftUI] imagePicker 사용해서 프로필 만들기 (0) | 2024.02.02 |
- Total
- Today
- Yesterday
- XCTest
- imagepicker
- ScrollViewReader
- LazyVGrid
- securefield
- mergeconflict
- OSLog
- UIKit
- Xcode
- rxswift
- CustomCalendar
- SWIFT
- 코딩테스트
- 병합충돌
- mlmodel
- ios
- ObservableObject
- 스위프트
- combine
- 16173
- 백준
- Fastlane
- 둘만의 암호
- closure
- 프로그래머스
- 클로저
- swiftUI
- CoreData
- 가장가까운같은글자
- MainActor
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |