This time your goal is to build a habit-tracking app, for folks who want to keep track of how much they do certain things. That might be learning a language, practicing an instrument, exercising, or whatever – they get to decide which activities they add, and track it however they want.
At the very least, this means there should be a list of all activities they want to track, plus a form to add new activities – a title and description should be enough.
For a bigger challenge, tapping one of the activities should show a detail screen with the description. For a tough challenge – see the hints below! – make that detail screen contain how many times they have completed it, plus a button incrementing their completion count.
And if you want to make the app really useful, use Codable and UserDefaults to load and save all your data.
So, there are three levels to this app, and you can choose how far you want to go depending on how much time you have and how far you want to push yourself. I do recommend you at least give each level a try, though – every little bit of practice you get helps solidify your learning!
먼저 가볍게 Habit struct를 만들고, NavigationLink로 해당 습관의 View로 이동하고, 그 View에서 도전한 횟수를 증가하고 저장할 수 있도록 했다.
디버깅 필요:
IExpense 프로젝트와 비슷하게 Habit을 Identifiable, Codable을 만족시켜 이를 @Obserbable인 class Habits에서 디코딩 하거나 인코딩하여 자동으로 UserDefaults에 저장했다.
달성 횟수가 화면에서 바로 업데이트가 되지 않고, 다시 로드가 되어야만 업데이트 되는 것을 해결하고자 힌트를 보았다. 힌트에서는 Equatable을 준수하는 habit도 복사하여 habits에서 habit을 찾아 업데이트 하는 형식을 알려준다.
읽던 중 habits 자체를 업데이트 하는 것이 아니라 다른 값을 복사하여 사용한다는 것에서 아이디어를 얻어 더 쉬운 방법으로 해결했다. HabitView에서는 habit뿐만 아니라 successCount
도 복사하여 @State로 전달받는다. 화면에서는 버튼과 동시에 업데이트 되는 @State로 나타내고, habit 또한 업데이트를 해준다. 이렇게 하면 값도 동기화되고, 화면에도 업데이트 사항을 바로 확인할 수 있다.
struct HabitView: View {
@Binding var habit: Habit
@State var successCount: Int
@State var buttonColor = Color.random()
var body: some View {
VStack {
Text("달성 횟수: \(successCount)")
// ...
Spacer()
Button(action: {
successCount += 1
habit.successCount = successCount
buttonColor = Color.random()
}, label: {
// ...