RxDataSources에서 여러 섹션에 여러 항목을 관리합니다.
10317 단어 RxDataSourcesRxSwift
RxDataSources 사용법
DataSource 정보
RxDataSources에 RxSwift의 RxCollectionViewDataSourceType
RxTableViewDataSourceType
에 준거하고 있는 class가 준비되어 있다.
이제 데이터 소스를 만들고 rx.items(dataSource:)
에 bind합니다.
UICollectionView의 경우
UITableView의 경우
SectionModelType 정보
각 DataSource를 사용하려면,
SectionModelType
, 혹은 AnimatableSectionModelType
에 준거하고 있는 형태를 준비할 필요가 있습니다.이 중의
items
가 그 Section내의 셀 모델에 해당합니다.protocol SectionModelType {
associatedtype Item
var items: [Item] { get }
init(original: Self, items: [Item])
}
※AnimatableSectionModelType의 경우는, 자신이
IdentifiableType
에 준거하고 있고, Item이 IdentifiableType
, Equatable
에 준거하고 있을 필요가 있습니다.protocol AnimatableSectionModelType: SectionModelType, IdentifiableType where Item: IdentifiableType, Item: Equatable {}
protocol IdentifiableType {
associatedtype Identity: Hashable
var identity : Identity { get }
}
RxDataSources는 위의 각각을 준수하는 다음 유형을 제공합니다.
struct SectionModel<Section, ItemType> {
var model: Section
var items: [Item]
init(model: Section, items: [Item]) {
self.model = model
self.items = items
}
}
struct AnimatableSectionModel<Section: IdentifiableType, ItemType: IdentifiableType & Equatable> {
var model: Section
var items: [Item]
init(model: Section, items: [ItemType]) {
self.model = model
self.items = items
}
}
구현해보기
한 섹션
준비되어 있는
AnimatableSectionModel<Section, ItemType>
를 사용해 구현해 봅니다.우선,
IdentifiableType
와 Equatable
에 준거하고 있는 형태를 준비합니다.struct Card: IdentifiableType, Equatable {
typealias Identity = String
var identity: String {
return id
}
let id: String
let color: UIColor
}
AnimatableSectionModel<String, Card>
로 취급하면 다음과 같은 형태가 됩니다.※Section은, RxDataSources로
extension String : IdentifiableType
가 준비되어 있으므로 그것을 사용하고 있습니다.var dataSource: RxCollectionViewSectionedAnimatedDataSource<AnimatableSectionModel<String, Card>> {
return RxCollectionViewSectionedAnimatedDataSource<AnimatableSectionModel<String, Card>>(
configureCell: { _, collectionView, indexPath, card -> UICollectionViewCell in
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "任意のidentifier", for: indexPath)!
cell.backgroundColor = card.color
return cell
})
}
cards.asObservable()
.map { cards: [Card] in
[AnimatableSectionModel<String, Card>(model: "", items: cards)]
}
.bind(to: collectionView.rx.items(dataSource: dataSource))
.disposed(by: disposeBag)
↓추가와 셔플과 삭제를 하고 있습니다.
애니메이션 있음 (섹션 1 개)
여러 섹션(공통 셀 모델)
Section이 복수 있는 경우는
AnimatableSectionModel<Section: IdentifiableType, ItemType: IdentifiableType & Equatable>
를 복수 건네주면 OK입니다.다만, 같은 identifier를 이용했을 경우, fatalError()가 되기 때문에 주의입니다.
※다른 Section, 다른 형태의 경우에서도 같은 identifier라면 안 된다
var dataSource: RxCollectionViewSectionedAnimatedDataSource<AnimatableSectionModel<String, Card>> {
return RxCollectionViewSectionedAnimatedDataSource<AnimatableSectionModel<String, Card>>(
configureCell: { model, collectionView, indexPath, card -> UICollectionViewCell in
// Section毎にcellを返す
let sectionModel = model.sectionModels[indexPath.section]
switch sectionModel.model {
case "1":
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "任意のidentifier", for: indexPath)!
cell.backgroundColor = card.color
return cell
case "2":
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "任意のidentifier", for: indexPath)!
cell.backgroundColor = card.color
return cell
default:
return UICollectionViewCell()
}
})
}
cards.asObservable()
.map { cards: [Card] in
// 雑ですが同じ値を使います。idだけ重複しないよう`2_`を先頭に加えています。
let copy = cards.map { Card(id: "2_\($0.id)", color: $0.color) }
return [AnimatableSectionModel<String, Card>(model: "1", items: cards),
AnimatableSectionModel<String, Card>(model: "2", items: copy)]
}
.bind(to: collectionView.rx.items(dataSource: dataSource))
.disposed(by: disposeBag)
애니메이션 있음 (섹션 2 개)
여러 섹션(여러 셀 모델)
다른 셀 모델의 경우 형식으로 래핑되어 캐스팅 할 준비가되어야합니다. (IdentifiableType, Equatable에 준거하고 있다)
이번에는 enum을 준비해 봅니다.
struct Item01: IdentifiableType, Equatable {
typealias Identity = String
var identity: Identity {
return id
}
let id: String
let color: UIColor
}
struct Item02: IdentifiableType, Equatable {
typealias Identity = String
var identity: Identity {
return id
}
let id: String
let color: UIColor
}
struct Item03: IdentifiableType, Equatable {
typealias Identity = String
var identity: Identity {
return id
}
let id: String
let color: UIColor
}
enum Item: IdentifiableType, Equatable {
typealias Identity = String
var identity: Identity {
switch self {
case .item01(let item):
return item.identity
case .item02(let item):
return item.identity
case .item03(let item):
return item.identity
}
}
case item01(Item01)
case item02(Item02)
case item03(Item03)
}
그리고는, 똑같이
RxCollectionViewSectionedAnimatedDataSource
를 구현합니다.셀을 생성하는 장소는 Section(String)이나 Item에서 기호에 분기로 OK입니다.
var dataSource: RxCollectionViewSectionedAnimatedDataSource<AnimatableSectionModel<String, Item>> {
return RxCollectionViewSectionedAnimatedDataSource<AnimatableSectionModel<String, Item>>(
configureCell: { model, collectionView, indexPath, item -> UICollectionViewCell in
let sectionModel = model.sectionModels[indexPath.section]
switch sectionModel.model {
case "0":
switch item {
case let .item01(i):
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "任意のidentifier", for: indexPath)
cell.backgroundColor = i.color
return cell
case let .item02(i):
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "任意のidentifier", for: indexPath)
cell.backgroundColor = i.color
return cell
case let .item03(i):
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "任意のidentifier", for: indexPath)
cell.backgroundColor = i.color
return cell
}
case "1":
switch item {
case let .item01(i):
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "任意のidentifier", for: indexPath)
cell.backgroundColor = i.color
return cell
case let .item02(i):
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "任意のidentifier", for: indexPath)
cell.backgroundColor = i.color
return cell
case let .item03(i):
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "任意のidentifier", for: indexPath)
cell.backgroundColor = i.color
return cell
}
default:
return UICollectionViewCell()
}
})
}
Observable
.combineLatest(item01.asObservable(),
item02.asObservable())
.map { (item01: [Item], item02: [Item]) in
return [AnimatableSectionModel<String, Item>(model: "0", items: item01),
AnimatableSectionModel<String, Item>(model: "1", items: item02)]
}
.bind(to: collectionView.rx.items(dataSource: delegate.dataSource))
.disposed(by: disposeBag)
애니메이션 있음 (섹션 2 개로 여러 셀 모델)
이상입니다!
그리고는, String으로 하고 있는 Section를 형태로 한, cell의 생성 부분을 정리하면 좋다고 생각합니다.
※덤(tvOS)
애니메이션 있음 (섹션 2 개로 여러 셀 모델)
Reference
이 문제에 관하여(RxDataSources에서 여러 섹션에 여러 항목을 관리합니다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/hryk224/items/1680dd3f751ed0b13de0텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)