Do.

DiffableDataSource와 Realm 본문

iOS

DiffableDataSource와 Realm

Hey_Hen 2022. 3. 3. 11:42

Issue

DiffableDataSource와 Realm을 함께 썼을 때 발생했던 문제와 해결법
DiffableDataSource는 Diff을 위해서 일종의 뷰의 상태를 가지고 있는데, 데이터가 변하면, 이전에 가지고 있던 상태와 비교해서 뷰를 갱신합니다.

Storage에서 Object3이 삭제가 되고, snapshot을 재 구성해서 dataSource에 apply를 실행하게 되면, 이전 DataSource Snapshot과 비교해서, 화면을 갱신하는 상황입니다.
그런데 해당 과정에서 Realm 예외처리 오류가 발생합니다.

   RealmManager.shared.deleteTodo(todo: todo)
    print(dataSource.snapshot().itemIdentifiers(inSection: .Task).map{($0 as! ToDo).task})

Realm에서 해당 데이터를 지운 후 dataSource에서는 아직 갱신이 되지 않았기 때문에, 해당 객체를 참조해볼 수 있는데, 프린트만 해도 에러가 납니다.

Terminating app due to uncaught exception 'RLMException', reason: 'Object has been deleted or invalidated.'
terminating with uncaught exception of type NSException

Realm Object로 생성한 객체는 Realm DB에서 삭제한 후에는 참조할 수 없도록, 예외처리가 들어가 있는 것 같습니다.
DiffableDataSource에서는 Diff을 위해, 삭제된 객체를 들고있어야 하는데, Realm에서 못들고 있게 하니까 snapshot을 apply 할 수 없게 되는 현상이 발생합니다.

Solution

1.

일반적인 DiffableDataSource 순서는
1. 스토리지에서 삭제
2. Snapshot 갱신
으로 볼 수 있는데, 이를 반대로 해볼 수 있습니다.
1. Snapshot 갱신
2. 스토리지에서 삭제

guard !todolist.isEmpty else { fatalError() }
    var snapshot = self.dataSource.snapshot()

    for todo in todolist {
      guard let _ = dataSource.indexPath(for: todo) else {
        print("delete error")
        return
      }
    }

 snapshot.deleteItems(todolist)
 dataSource.apply(snapshot, animatingDifferences: true)

 RealmManager.shared.deleteTodo(todo: todo)

근데 이러면 DiffableDataSource를 쓰는 의미가 없죠, DiffableDataSource의 장점은, 언제든 ConfigureSnapshot만 호출하면 되는 부분이 중요한데 말이죠!
그래서 다른 방법!

2.

1.의 솔루션을 조금 다르게 생각해서
DiffableDataSource에서 Diff 연산을 하고 난 뒤에 스토리지에서 삭제하는 컨셉은 똑같이 생각합니다.

기존에는 Realm DB에서 삭제를 이렇게 해버렸다면

바로 삭제하지 않고, 삭제한 데이터를 관리하는 섹션으로 따로 관리하는 거죠
Realm 내부에서 삭제된 데이터를 관리하는 별도의 모델을 만들거나

원래 모델에 isDelete: Bool 를 추가해서 필터링 해서 가져오는 방법도 있죠

 

More

애초에 사용자 경험 관점에서, 삭제를 바로 해버리는 것 보다는 안전장치를 두는게 더 좋은 선택일 수도 있다고 생각이 드네요

Realm Delete를 설명하는 문서

문서를 읽읍시다. ^^

'iOS' 카테고리의 다른 글

iOS - URLCache  (0) 2022.03.21
Run Loop vs DispatchQueue  (0) 2022.03.13
Swift- CoreBluetooth 찍먹  (0) 2022.03.01
NMapsMap M1 Build Error  (0) 2022.02.26
Diffable Data Source  (3) 2022.02.18
Comments