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 라이센스를 따릅니다.