Todoey (8)
Query 작성하기.
지금 Query에 해당하는 부분은 SearchBar에 대한 부분 밖에 없다.
그 부분의 내용을 고쳐보도록 하자.
todoItems = todoItems?.filter(<#T##predicateFormat: String##String#>, <#T##args: Any...##Any#>)
에서 필터를 사용한 것을 다시 todoitems에 담는다.
predicateFormat에는 NSpredicateFormat과 동일하게 작성한다.
즉,
"title CONTAINS[cd] %@"
이 부분이 그대로 들어간다는 뜻
todoItems = todoItems?.filter("title CONTAINS[cd] %@", searchBar.text!)
이렇게 된다.
NSpredicate사용했을때와 비교하면 let predicate = NSPredicate(format: "title CONTAINS[cd] %@", searchBar.text!)
내용은 같다.
하지만 이전에는 필터링한 결과를 가지고 소팅을 했다면 이번엔 바로 소팅 메서드를 연결할 수 있다.
todoItems = todoItems?.filter("title CONTAINS[cd] %@", searchBar.text!).sorted(byKeyPath: "title", ascending: true)
이전에 길었던 코드가 한줄로 해결이 되는 매직이 발생했다.
1. 날짜를 기준으로 소팅해보기
@objc dynamic var dateCreated: Date?
생성
newItem.dateCreated = Date()
도 추가.
1
2
3
error: 'try!' expression unexpectedly raised an error: Error Domain=io.realm Code=10 "Migration is required due to the following errors:
- Property 'Item.dateCreated' has been added." UserInfo={Error Name=SchemaMismatch, NSLocalizedDescription=Migration is required due to the following errors:
- Property 'Item.dateCreated' has been added., Error Code=10}
다음과 같은 에러가 뜬다.
현재 DB에는 dateCreated라는 속성이 없기에 발생한 문제!
즉 에러에서 말하는 그대로 Migration이 필요하다는 것이다.
2. Migration 하기
앱을 삭제하자!
즉 새로운 Realm파일로 시작하는 의미.
새로 생긴걸 알 수 있다.
값을 추가하니 date가 잘 나오는걸 알 수 있다.
Swipe하여 삭제기능 구현
CocoaPod의 라이브러리를 사용할것이다.
사이트에 정보가 나와있다.
예시를 바탕으로 코드 수정
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// sample
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as! SwipeTableViewCell
cell.delegate = self
return cell
}
// modified
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CategoryCell") as! SwipeTableViewCell
cell.textLabel?.text = categories?[indexPath.row].name ?? "No Categories added Yet"
cell.delegate = self
return cell
}
1. extension을 사용하여 코드 확장
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
extension CategoryViewController: SwipeTableViewCellDelegate {
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath, for orientation: SwipeActionsOrientation) -> [SwipeAction]? {
guard orientation == .right else { return nil } // swipe 방향
let deleteAction = SwipeAction(style: .destructive, title: "Delete") { action, indexPath in
// handle action by updating model with deletion
}
// customize the action appearance
deleteAction.image = UIImage(named: "delete")
return [deleteAction]
}
}
안의 함수는 현재 readme에 있는 코드내용.
이제 안의 함수부를 수정 할 예정이다.
이미지는 사이트의 이미지를 사용했다.
실행했더니 App Crash가 발생했다.
1
Could not cast value of type 'UITableViewCell' (0x1ec2f2b10) to 'SwipeCellKit.SwipeTableViewCell' (0x101eeeda0).
UITableViewCell을 SwipeCellKit.SwipeTableViewCell로 캐스팅을 할 수 없다고 나왔다.
여기에 Class가 UITableViewCell로 default가 잡혀있는데,
이부분을 바꿔주어야한다.
이렇게 바꿔준다. 모듈도 꼭 확인해보고 체크해두자.
확인해보니 현재 사이즈가 맞지않는다.
조절을 해야할것같다.
tableView.rowHeight = 85.0
각 셀의 높이를 85으로 주었다.
사진은 업로드 하지않았지만 꽤 괜찮다.
삭제를 하는 코드를 넣어보자.
우선 내 기억대로 해보았는데 에러가 발생했다.
1
2
3
4
5
6
do {
self.realm.delete(currentCategory)
} catch {
print("Error \(error.localizedDescription)")
}
Exception Error가 발생했다.
내용은 다음과 같다.
1
*** Terminating app due to uncaught exception 'RLMException', reason: 'Can only add, remove, or create objects in a Realm in a write transaction - call beginWriteTransaction on an RLMRealm instance first.'
이전에 작성한걸 보았다.
1
2
3
4
5
6
7
8
do {
try realm.write {
item.done = !item.done
}
} catch {
print("Error Saving New Items, \(error.localizedDescription)")
}
realm.write를 빼먹었다.
분명히 기억에 try도 썼는데 어디갔나 했다.
잘 기억해두자.
1
2
3
4
5
6
7
8
9
10
11
if let currentCategory = self.categories?[indexPath.row] {
do {
try self.realm.write {
self.realm.delete(currentCategory)
}
} catch {
print("Error \(error.localizedDescription)")
}
tableView.reloadData() // new
}
reloadData를 안하니 에러가 발생했다.
문제를 바로 확인하고 추가하니 작동이 잘 된다.
기능 추가
1
2
3
4
5
func tableView(_ tableView: UITableView, editActionsOptionsForRowAt indexPath: IndexPath, for orientation: SwipeActionsOrientation) -> SwipeOptions {
var options = SwipeOptions()
options.expansionStyle = .destructive
return options
}
Readme에 있는 부분을 가져와서 추가했다.
완료.