To Do List (3)
CellView 적용하기
1
2
3
4
List(todoLists, id: \.self) { list in
CellView(isOn: list.isCompleted,
title: list.title)
}
MainView에서 List에 다음과 같이 CellView를 적용시켜준다.
Toggle 버튼 클릭시 적용하기.
On/Off에 따라 AttributedText가 적용되게 해보자.
SwiftUI에서는 Text에 바로 stirkethrough Modifier가 있다.
isOn이 toggle에 따라 true/ false가 바뀌므로
1
2
3
4
5
6
7
HStack {
Text(title)
.strikethrough(isOn, color: .black)
.padding(.leading, 30)
Toggle("", isOn: $isOn)
.padding(.trailing, 30)
}
이렇게 해주면 작동이 된다.
LV 2 까지 완료.
Swipe를 이용한 삭제기능 구현
여기는 LV3이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
VStack {
List(todoLists, id: \.self) { list in
CellView(isOn: list.isCompleted,
title: list.title)
.swipeActions(edge: .trailing) {
Button(action: {
modelContext.delete(list)
}) {
Image(systemName: "trash")
}
}
}
}
그리고 Button에 빨간색 배경을 주고 싶었는데 거기에 하는게 아니라,
SwipeAction의 마무리에 tint를 사용해서 적용해야한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
VStack {
List(todoLists, id: \.self) { list in
CellView(isOn: list.isCompleted,
title: list.title)
.swipeActions(edge: .trailing) {
Button(action: {
modelContext.delete(list)
}) {
Image(systemName: "trash")
}
}
.tint(.red)
}
}
LV 3 완료.
이떄 tint red로 인해
이렇게 toggle까지 변하게 된다.
그래서 이부분은 초록색으로 유지하기 위해서
1
2
3
4
5
6
7
8
9
HStack {
Text(title)
.strikethrough(isOn, color: .black)
.padding(.leading, 30)
.lineLimit(0)
Toggle("", isOn: $isOn)
.padding(.trailing, 10)
.tint(.green)
}
CellView에도 tint를 적용시켜준다.
적용 완료.
List를 id순으로 정렬하기
현재는 등록시 규칙없이 추가가 되는듯 하다.
@Query(sort: \TodoModel.id) private var todoLists: [TodoModel]
sort를 붙여주면 해결된다.
id 중복 수정하기.
현재 id 가
이렇게 순서대로 정렬이 되지만
1
2
3
4
5
6
func addList() {
let id: Int = todoLists.count
let todoModel = TodoModel(id: id + 1, title: title, isCompleted: false)
modelContext.insert(todoModel)
title = ""
}
이렇게 현재 갯수에서 1씩 증가를 하는 매커니즘으로 되어있다.
중복을 방지하기위해 현재 리스트에 있는 값에서 최대값을 구한뒤 거기서 1을 더하게 한다.
1
2
3
4
5
6
7
func chkId(_ currentId: Int) -> Int {
var id = currentId
if let maxId = todoLists.map({ $0.id }).max() {
id = maxId + 1
}
return id
}
전부 지우기
사이트 를 참고한다.
1
2
3
4
5
6
7
8
9
10
11
12
ToolbarItem(id: "DeleteAll",
placement: .navigationBarLeading) {
Button("DeleteAll",
systemImage: "folder.badge.minus") {
// action
do {
try modelContext.delete(model: TodoModel.self)
} catch {
print("Error: \(error.localizedDescription)")
}
}
}
이때 하나의 row를 삭제할때는 try - catch 구문이 없었는데
전체삭제는 해줘야한다.
Coredata와 유사하다.
회고.
1. Comparable vs Equatable
- 역할
- Comparable은 객체 간에 순서를 비교할 수 있게 한다. 이를 통해 두 객체가 크거나 작은지(<, <=, >, >=)를 비교하여 정렬이 가능해진다.
- 필요성
- 정렬이 필요한 경우, 예를 들어 배열을 오름차순 또는 내림차순으로 정렬할 때 Comparable이 사용된다. 이 프로토콜은 객체 간의 대소 비교를 위한 연산자를 제공한다.
- 구현 방법
- Comparable을 구현하려면 < 연산자를 구현해야 한다. 그 외의 연산자(>, <=, >=)는 기본적으로 제공된다. Comparable을 준수하려면 Equatable도 함께 구현해야 하므로, 객체 간의 동등성과 순서를 모두 정의할 수 있다.
ex)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
struct Person: Comparable {
let name: String
let age: Int
static func < (lhs: Person, rhs: Person) -> Bool {
return lhs.age < rhs.age
}
// Equatable의 구현도 필요함
static func == (lhs: Person, rhs: Person) -> Bool {
return lhs.age == rhs.age && lhs.name == rhs.name
}
}
let person1 = Person(name: "Alice", age: 30)
let person2 = Person(name: "Bob", age: 25)
print(person1 < person2) // false
print(person1 > person2) // true
let sortedPeople = [person1, person2].sorted()
print(sortedPeople) // [Person(name: "Bob", age: 25), Person(name: "Alice", age: 30)]
- 역할
- Equatable은 객체가 서로 같은지 여부를 비교하는 데 사용된다. 이를 통해 두 객체가 동등한지(==) 또는 동등하지 않은지(!=)를 알 수 있다.
- 필요성
- Equatable은 데이터가 같은지 비교할 수 있어야 하는 여러 곳에서 필수적이다. 예를 들어, 배열에서 특정 객체를 찾거나, 두 객체가 같은지 비교할 때 사용된다.
- 구현 방법
- Equatable을 준수하려면 == 연산자를 구현해야 한다. 두 객체가 같은지 확인하기 위해, 각 객체의 속성을 비교한다.
ex)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
struct Person: Equatable {
let name: String
let age: Int
static func == (lhs: Person, rhs: Person) -> Bool {
return lhs.name == rhs.name && lhs.age == rhs.age
}
}
let person1 = Person(name: "Alice", age: 30)
let person2 = Person(name: "Alice", age: 30)
let person3 = Person(name: "Bob", age: 25)
print(person1 == person2) // true
print(person1 == person3) // false
결론
Equatable은 두 객체가 동일한지 확인하는 데 사용되고, Comparable은 객체들 간의 순서 비교와 정렬을 할 때 사용된다. Comparable을 구현하려면 반드시 Equatable을 함께 구현해야 하므로, Comparable을 준수하는 객체는 동등성(==)과 순서 비교(<) 모두 가능하다.
이 두 프로토콜을 잘 활용하면 데이터 비교와 정렬 작업을 효율적으로 처리할 수 있다.
프로토콜 | 주요 연산자 | 목적 | 필수 메서드 | 사용 예시 |
---|---|---|---|---|
Equatable | == , != | 두 객체가 동일한지 비교 | static func ==(lhs:rhs:) -> Bool | 객체가 같은지 비교할 때 (Array.contains() ) |
Comparable | < , <= , > , >= | 두 객체 간 순서를 비교 | static func <(lhs:rhs:) -> Bool | 배열 정렬, 대소 비교 (Array.sorted() ) |