개발콩블로그
[트러블슈팅] DiffableDataSource + RealmSwift 본문
안녕하세요 개발콩입니다!🫛
최근에 DiffableDataSource와 RealmSwift를 공부하게 되었습니다!
Local Data를 CollectionView에 표현할 때 애니메이션이 있으면 조금 더 사용자에게 UX적으로 좋은 경험을 줄 수 있을 것 같아
이 두가지를 함께 시도하게 되었습니다!
하지만 이 둘을 함께 사용하면서 문제가 발생하였고, 앞으로 이 두가지를 동시에 사용할 때 고려하면 좋을 것 같아 글을 남기게됩니다.
문제 상황
Realm을 통해 DataSource 배열을 만들어 주었고, 해당 데이터를 사용하여 NSDiffableDataSourceSnapshot을 만들고 업데이트를 진행했습니다.
하지만, 특정 데이터를 삭제하던 도중 앱이 크래쉬가 발생했습니다.
원인 분석
- 특정 Cell을 클릭하면 Realm에서 데이터를 지웁니다.
- 변경된 데이터를 다시 snapshot을 통해 업데이트 합니다.
- snapshot은 캡쳐를 활용하여 이전 데이터와 현재 반영된 데이터를 비교합니다.
- 기존의 데이터는 삭제되었지만 해당 데이터를 참조하여 사용하기 때문에 앱이 크래쉬가 발생했습니다.
목표
NSDiffableDataSourceSnapshot 방법을 사용하지 않고, 일반적인 DataSource를 사용하여 reloadData()를 사용하게 된다면 문제는 해결될 것으로 보였습니다.
하지만 저의 목표는 사용자에게 더 나은 UX를 제공하기 위해 애니메이션을 보여주는 것 입니다.
따라서 NSDiffableDataSourceSnapshot을 사용하면서 문제를 해결하고 싶었습니다.
해결 방법
문제가 발생하는 지점은 삭제된 이전 데이터와 현재 데이터를 비교하는 부분에서 발생합니다.
따라서, 데이터 삭제 시점을 데이터 반영 시점 이후로 변경했습니다.
전체적인 코드 대신에 해결 흐름을 보일 수 있는 코드를 작성했습니다. 각각의 아키텍처 구조는 다를 수 있기 때문에 해결 흐름만 알고있다면 적용하기 쉬울 것 같습니다.
삭제해야할 dataStack을 만듭니다.
private var deleteStack: [ProductEntity] = []
삭제하는 시점에 해당 데이터를 직접적으로 삭제하는 것이 아닌, filter를 사용하여 삭제할 데이터를 제외한 나머지 데이터를 반환합니다.
owner.deleteStack.append(product) // 삭제할 stack에 추가
// 삭제 대신 filter를 통해 해당 데이터를 제외한 나머지 데이터 반환
Array(owner.realm.objects(FavoriteProduct.self).where { $0.productId != product.productId })
이후, 업데이트가 완료된 시점에 삭제하는 트리거를 보내줍니다.
private func updateSnapshot(with product: [FavoriteProduct]) {
var snapshot = NSDiffableDataSourceSnapshot<FavoriteViewModel.Section, FavoriteProduct>()
snapshot.appendSections(FavoriteViewModel.Section.allCases)
snapshot.appendItems(product, toSection: .favorite)
dataSource.apply(snapshot)
updateSnapShotRelay.accept(()) // 업데이트가 완료되었음을 알려줍니다.
}
트리거를 받은 시점에 해당 데이터를 삭제합니다.
input.updateSnapShot
.bind(with: self) { owner, _ in
guard let deleteData = owner.deleteStack.popLast() else { return }
owner.deleteFavoriteProductRealm(with: deleteData) // 삭제하는 로직
}
.disposed(by: disposeBag)
결론
- snapshot을 사용하는 것은 이전 데이터를 참고하기 때문에 삭제된 데이터를 참조합니다.
- realm은 참조 타입이기 때문에 삭제된 데이터가 삭제된 주소에 참조할 수 있습니다.
- 실제로 삭제되는 시점을 변경하여 원하는 동작을 수행할 수 있습니다.
'트러블슈팅' 카테고리의 다른 글
[트러블 슈팅] iOS CLLocation GPS 보정하기(with 칼만 필터) (1) | 2025.04.12 |
---|---|
[트러블슈팅] 중첩 클로저로 인한 순환 참조 및 메모리 누수 해결하기 (1) | 2025.02.21 |