To Do List (5)
수정기능 마무리
1
2
3
4
5
6
func modifyList(title: String) {
        let i = todoLists.firstIndex { list in
            list.title == title
        }
        todoLists[i!].title = title
    }
함수를 이렇게 적용하였으나
바뀌지 않았다.
생각해보니 파라미터를 잘못했다.
1
2
3
4
5
6
func modifyList(currentTitle: String, modifiedTitle: String) {
        let i = todoLists.firstIndex { list in
            list.title == currentTitle
        }
        todoLists[i!].title = modifiedTitle
    }
이렇게 해주니 성공.
찾아보니 SwiftData는 Update를 해줄 필요가 없다고한다. 데이터가 바뀌면 자동으로 Save가 된다고한다.
완료.
Cell클릭시 화면 전환하기
NavigationLink를 사용한다.
이때 주의점은 NavigationLink를 사용하기전에 NavigationView가 있어야 한다는것.
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
var body: some View {
        NavigationStack {
            NavigationView {
            VStack {
                List(todoLists, id: \.self) { list in
                        NavigationLink(value: list) {
                            CellView(isOn: list.isCompleted,
                                     title: "\(list.title)")
                            .swipeActions(edge: .trailing) {
                                Button(action: {
                                    modelContext.delete(list)
                                }) {
                                    Image(systemName: "trash")
                                }
                            }
                            .tint(.red)
                            .swipeActions(edge: .leading) {
                                Button("edit",
                                       systemImage: "pencil") {
                                    isEditing.toggle()
                                    tempoList = list
                                }
                            }
                            .tint(.blue)
                            .alert("TodoList 수정",
                                   isPresented: $isEditing) {
                                TextField("수정", text: $title)
                                Button("OK",
                                       role: .cancel) {
                                    if let currentTitle = tempoList?.title {
                                        modifyList(currentTitle: currentTitle, modifiedTitle: title)
                                    }
                                    title = ""
                                }
                                Button("Cancel", role: .destructive){
                                    
                                }
                            }
                        }
                    }
                    .navigationTitle("ToDoList")
                    .navigationDestination(for: TodoModel.self) { list in
                        DetailView(title: list.title)
                    }
                }
            }
            .toolbar {
                ToolbarItem(id: "add",
                            placement: .navigationBarTrailing) {
                    Button("add",
                           systemImage: "plus.app") {
                        isShowing.toggle()
                    }
                           .alert("TodoList 추가",
                                  isPresented: $isShowing) {
                               
                               TextField("TodoList 추가", text: $title)
                               Button("OK",
                                      role: .cancel) {
                                   addList()
                               }
                               Button("Cancel", role: .destructive){
                                   title = ""
                               }
                           }
                }
                ToolbarItem(id: "DeleteAll",
                            placement: .navigationBarLeading) {
                    Button("DeleteAll",
                           systemImage: "folder.badge.minus") {
                        do {
                            try modelContext.delete(model: TodoModel.self)
                        } catch {
                            print("Error: \(error.localizedDescription)")
                        }
                    }
                }
            }
        }
    }
코드가 꽤나 길어졌다.
Navigation Area 조절
빨간색 박스 부분이 Hierarchy로 확인해보니
NavigationBarLargeTitleView(하단), NavigationBarContentView(상단)로 나온다.
Vstack을 지우고
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
32
33
34
35
36
37
38
39
40
41
42
NavigationView {
                List(todoLists, id: \.self) { list in
                    NavigationLink(value: list) {
                        CellView(isOn: list.isCompleted,
                                 title: "\(list.title)")
                        .swipeActions(edge: .trailing) {
                            Button(action: {
                                modelContext.delete(list)
                            }) {
                                Image(systemName: "trash")
                            }
                        }
                        .tint(.red)
                        .swipeActions(edge: .leading) {
                            Button("edit",
                                   systemImage: "pencil") {
                                isEditing.toggle()
                                tempoList = list
                            }
                        }
                        .tint(.blue)
                        .alert("TodoList 수정",
                               isPresented: $isEditing) {
                            TextField("수정", text: $title)
                            Button("OK",
                                   role: .cancel) {
                                if let currentTitle = tempoList?.title {
                                    modifyList(currentTitle: currentTitle, modifiedTitle: title)
                                }
                                title = ""
                            }
                            Button("Cancel", role: .destructive){
                                
                            }
                        }
                    }
                }
            }
            .navigationTitle("ToDoList")
            .navigationDestination(for: TodoModel.self) { list in
                DetailView(title: list.title)
            }
NavigationView에 modifier를 적용하니 해결이 되었다.
SearchBar 만들기
YouTube를 참고하여 만들었다.
.searchable(text: $searchText, placement: .navigationBarDrawer, prompt: "Todo Search")
이걸 나는 NavigationStack쪽에 Modifier를 달아주었다.
하지만 적용은 되지 않는데, 이제 필터링 되는 리스트를 만들어 준다.
1
2
3
4
5
var filteredList: [TodoModel] {
        guard !searchText.isEmpty else { return todoLists }
        return todoLists.filter { $0.title.localizedCaseInsensitiveContains(searchText)}
    }
    
여기서 포인트는
- 입력을 아무것도 안 했을 때: searchText가 비어 있으면todoLists전체를 그대로 반환한다.
- 입력을 했을 경우:- searchText가 비어 있지 않으면- todoLists를 필터링하여, 각 항목의- title이- searchText를 대소문자 구분 없이 포함하는지 확인한다.
- 일치하는 항목들만 담은 배열을 반환한다.
 
localizedCaseInsensitiveContains?
- 역할: localizedCaseInsensitiveContains는 문자열이 특정 텍스트를 포함하고 있는지 확인하는 메서드다.
- 특징:- 대소문자를 구분하지 않고(caseInsensitive) 비교한다.
- 로케일에 맞게 비교하여, 언어별 특수 문자를 인식한다.
 
- 대소문자를 구분하지 않고(
- 예시:- title.localizedCaseInsensitiveContains("todo")는- title이 “todo”를 포함하는지 확인하며, “Todo”, “TODO” 등 대소문자 차이를 무시하고 비교한다.
 
 이 기사는 저작권자의  CC BY 4.0  라이센스를 따릅니다.