#0 - 기존 코드의 문제점과 이를 해결할 구조를 설계하는 과정
문제점 해결을 위한 전체 구상도
- ViewModel 내부에서 데이터 베이스의 연동 작업과 네트워크 서비스 등 다양한 서비스 작업을 구현한다.
- 옵저버를 이용하여 값의 변화를 방출해 DiffableDataSource에서 필요한 작업, 뷰 컨트롤러 내부 다양한 뷰 컴포넌트에서 필요한 작업을 분리할 수 있다.
DiffableDataSource 실제 프로젝트 적용시 문제점
⛔ 요약: 엄청난 양의 작업들을 뷰 컨트롤러에서 처리해야함으로 뷰 컨트롤러의 코드 양이 늘어나고 로직 구성이 엄청나게 복잡했다.
1. Realm 데이터베이스용 모델 데이터와 DiffableDataSource용 모델 데이터를 따로 관리해야한다.
⇒ 관리용 코드를 작성해야한다.
DiffableDataSource와 Realm
Issue DiffableDataSource와 Realm을 함께 썼을 때 발생했던 문제와 해결법 DiffableDataSource는 Diff을 위해서 일종의 뷰의 상태를 가지고 있는데, 데이터가 변하면, 이전에 가지고 있던 상태와 비교해서 뷰를
doing-programming.tistory.com
Realm and Diffable Data Source
Has anyone tried to use Realm in conjunction with diffable data sources? There seems to be an issue I can't get my head around. So, when when we use the "traditional" data source API, in
stackoverflow.com
⇒ RealmData 모델을 바로 DiffableDataSource 모델로 적용할시 발생하는 문제점들
💡 - DB로 Realm을 사용하는데 데이터 베이스에 존재하는 데이터들을 가져오는 테이블 인스턴스는 모두 클래스의 인스턴스이다. - 데이터베이스 primaryKey가 Identifiable, Hashable을 만족시켜 DiffableDataSource Item로 사용할 수 있으나, Realm 테이블 인스턴스는 DB에서 삭제된 후, 참조할 수 없는 문제와 같은 제약이 있었다.
- 이를 해결하기 위해 Database용 클래스 인스턴스를 DiffableDataSource용 구조체 인스턴스로 바꾸어 적용하기로 결정했다.
❗ 사실 이렇게 타입을 바꾸는 것이 절대적인 해결법이 아닐 수 있다.
⇒ 그러나, 데이터들을 값 타입으로 관리하며 얻는 장점이 추가로 생겨서 이 해결법을 결정했다.
장점들
- 데이터 인스턴스에 Reference Count를 신경쓰지 않아도 된다.
- ⭐ 값 타입으로 데이터들을 그대로 복사해 수정하거나 조작하기 더 수월해진다.
- 뷰 렌더링을 위해 빠른 처리가 필요한 DiffableDataSource의 데이터 가공 작업 실행시 비용 소모가 상대적으로 더 적다.
단점
- DataSource용 데이터 모델과 DataBase간의 변경 사항을 적용하는 동기화 작업을 각각의 화면에 맞게 추가로 작성해야한다.
⇒ 고려사항이 늘어난 것이기도 하다…
2. 셀 데이터를 관리하는 모델 데이터를 뷰 컨트롤러가 갖고 있다.
final class TempVC: UIViewController{
enum MediaType{
case video
case music
case shortVideo
}
struct Item:Identifiable,Hashable{
var id:UUID
var itemType: MediaType
}
var videoStore:AnyModelStore<VideoItem>!
var shortVideoStore:AnyModelStore<ShortVideo>!
var musicStore: AnyModelStore<MusicItem>!
var dataSource: UICollectionViewDiffableDataSource<MediaType,Item>!
override func viewDidLoad() {
super.viewDidLoad()
var snapshot = NSDiffableDataSourceSnapshot<MediaType,Item>()
var videoItems = (0...20).map{_ in VideoItem()}
var shortVideoItems = (0...40).map{_ in ShortVideo()}
var musicItems = (0...60).map{_ in MusicItem()}
videoStore = .init(videoItems)
shortVideoStore = .init(shortVideoItems)
musicStore = .init(musicItems)
snapshot.appendSections([.video,.music,.shortVideo])
snapshot.appendItems(videoItems.map{Item(id: $0.id, itemType: .video)},toSection: .video)
snapshot.appendItems(musicItems.map{Item(id: $0.id, itemType: .music)},toSection: .music)
snapshot.appendItems(shortVideoItems.map{Item(id: $0.id, itemType: .music)},toSection: .shortVideo)
dataSource.apply(snapshot,animatingDifferences: true)
}
...
다양한 셀을 그리는 DiffableDataSource 데이터 구성하기 #2
AnyModelStore의 필요성 접근 문제 → 아이템 접근을 first로 한다. (순회 발생) var musicRegistration: UICollectionView.CellRegistration{ UICollectionView.CellRegistration { cell, indexPath, itemIdentifier in guard itemIdentifier.itemType
arpple.tistory.com
⇒ 여기에서 다룬 예제 코드이다… 뷰 컨트롤러에 데이터 모델 초기화에만 엄청난 양의 코드가 존재한다..!
3. DiffableDataSource의 데이터를 가공하는 작업 코드를 뷰 컨트롤러가 갖고 있다.
4. DataSource용 데이터 모델과 DataBase간의 변경 사항을 적용하는 코드를 추가로 작성해야한다. 그리고 코드를 뷰 컨트롤러가 갖고있다.
⇒ 데이터베이스를 다룬 후 추가적인 DataSource 로직을 뷰 컨트롤러에서 또 다루어야한다.
CustomDiffableDataSource를 제작하기
어떻게 위에 문제를 처리할까 고민하다 Swipe Delete 기능 구현 방법을 찾던 중 DataSource를 상속하는 것을 보고 이를 이용해서 위의 문제를 해결 할 수 있겠다 생각했다.
➕ 역시 애플 공식 문서에 코드가 존재했다.
Implementing Modern Collection Views | Apple Developer Documentation
Bring compositional layouts to your app and simplify updating your user interface with diffable data sources.
developer.apple.com
Unable to swipe to delete with tableview using diffable data source in iOS 13
I'm updating a UITableViewController to use the new UITableViewDiffableDataSource, I have everything working except Swipe to delete. This is an example of how I use swipe to delete func tableView(_
stackoverflow.com
CustomDiffableDataSource에 옮길 뷰 컨트롤러 코드와 옮긴 후 문제점
뷰 컨트롤러에서 옮기기로 바로 결정한 작업 코드들은 다음과 같다
- 셀 데이터를 관리하는 모델 데이터 프로퍼티 코드
- DiffableDataSource의 데이터를 가공하는 작업 코드
고려할 문제점은 다음과 같다.
- 데이터 베이스와 DiffableDataSource를 연동시키는 작업은 어디에 둬야하나?
- 위에 CustomDiffableDataSource에 들어갈 데이터 관리 모델 데이터와 뷰 컨트롤러와 서로 연결할 작업 코드는 어디에 두어야하나?
💡 이 두가지의 문제점은 결국 코드를 분리하며 하나의 화면에서 여러 인스턴스(데이터베이스, 데이터소스, 뷰 처리…)간의 연결을 어떻게 처리할지에 대한 문제점이었다. 이런 문제를 해결하기 위해 ViewController에 맞는 ViewModel을 만들어서 여러 인스턴스간의 연결을 관리하기로 결정했다.
'이모저모 > UIKit' 카테고리의 다른 글
싱글톤 앨범 이미지 서비스 만들기 with Rx or Combine (0) | 2023.11.28 |
---|---|
UIButton State 애니메이션용 모듈 만들고 적용하기 (0) | 2023.11.25 |
다양한 셀을 그리는 DiffableDataSource 데이터 구성하기 #2 (0) | 2023.11.10 |
다양한 셀을 그리는 DiffableDataSource 데이터 구성하기 #1 (0) | 2023.11.10 |
애플 앱 프로필 버튼 만들기 (0) | 2023.09.15 |
댓글