๐กWhy
๊ธฐ์กด์ table๊ณผ collection view์์์ ๋ฐฉ๋ฒ๋ค๋ณด๋ค ๊ฐ๋จํ๊ฒ ๊ตฌํํ ์ ์๋ delegate method๋ค์ด ๋ง์ด ์์ต๋๋ค.
RxSwif๋ ๊ฐ๋จํ data binding์ ํตํด ์ง์ ๋์ด์ค๋๋ค.
- data๋ฅผ Observable sequence๋ก ๋ฐ๊ฟ์ค๋๋ค.
- ๋ค์์ ์ฌ์ฉํด์ data๋ฅผ bind ํฉ๋๋ค
- rx.items(dataSource:protocol<RxTableViewDataSourceType, UITableViewDataSource>)
- rx.items(cellIdentifier:String)
- rx.items(cellIdentifier:String:Cell.Type:_:)
- rx.items(::)
let data = Observable<[String]>.just(["first element", "second element", "third element"])
data.bind(to: tableView.rx.items(cellIdentifier: "Cell")) { index, model, cell in
cell.textLabel?.text = model
}
.disposed(by: disposeBag)
์ด๋ฐ ๋ฐฉ๋ฒ์ ๊ฐ๋จํ data ์ธํธ์์๋ ์ ์๋ํ์ง๋ง section์ด ๋ง์ ๋ณต์กํ data set์ธ ๊ฒฝ์ฐ, adding/modifying/deleting ํ ๋ animation ์ํ์ด ํ์ํ ๋ ์ ์๋ํ์ง ์์ต๋๋ค.
## ๐กHow
๋ค์ data structrue๋ฅผ ์ฌ์ฉํ๋ค.
struct CustomData {
var anInt: Int
var aString: String
var aCGPoint: CGPoint
}
SectionModelType
protocol์ ๋ฐ๋ฅด๋ struct๋ก section์ ์ ์ํ๋ค.
struct SectionOfCustomData {
var header: String
var items: [Item]
}
extension SectionOfCustomData: SectionModelType {
typealias Item = CustomData
init(original: SectionOfCustomData, items: [Item]) {
self = original
self.items = items
}
}
- dataSource ๊ฐ์ฒด๋ฅผ ๋ง๋ค๊ณ
SectionOfCustomData
ํ์ ์ ์ ๋ฌํ๋ค.
let dataSource = RxTableViewSectionedReloadDataSource<SectionOfCustomData>(
configureCell: { dataSource, tableView, indexPath, item in
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = "Item \(item.anInt): \(item.aString) - \(item.aCGPoint.x):\(item.aCGPoint.y)"
return cell
})
- ํ์์๋ฐ๋ผ dataSource์ closure๋ฅผ ์ปค์คํ ํฉ๋๋ค.
dataSource.titleForHeaderInSection = { dataSource, index in
return dataSource.sectionModels[index].header
}
dataSource.titleForFooterInSection = { dataSource, index in
return dataSource.sectionModels[index].footer
}
dataSource.canEditRowAtIndexPath = { dataSource, indexPath in
return true
}
dataSource.canMoveRowAtIndexPath = { dataSource, indexPath in
return true
}
- CustomData์ Observable sequence๋ก ์ค์ data๋ฅผ ์ ์ํ๋ค.
let sections = [
SectionOfCustomData(header: "First section", items: [CustomData(anInt: 0, aString: "zero", aCGPoint: CGPoint.zero), CustomData(anInt: 1, aString: "one", aCGPoint: CGPoint(x: 1, y: 1)) ]),
SectionOfCustomData(header: "Second section", items: [CustomData(anInt: 2, aString: "two", aCGPoint: CGPoint(x: 2, y: 2)), CustomData(anInt: 3, aString: "three", aCGPoint: CGPoint(x: 3, y: 3)) ])
]
Observable.just(sections)
.bind(to: tableView.rx.items(dataSource: dataSource))
.disposed(by: disposeBag)
RxdataSoureces๋ ์๋์ผ๋ก animating ๋ณํ๋ฅผ ๊ด๋ฆฌํด์ฃผ๋ ๋๊ฐ์ง data source ํ์ ์ด ์์ต๋๋ค.
- RxTableViewSectionedAnimatedDataSource
- RxCollectionViewSectionedAnimatedDataSource
2๊ฐ์ data source์ค ํ๋๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ๋ช ๊ฐ์ง ์ถ๊ฐ ๋จ๊ณ๊ฐ ํ์ํฉ๋๋ค.
- SectionOfCustomData๋
AnimatableSectionModelType
๋ฅผ ์ค์ํด์ผํฉ๋๋ค. - ๋น์ ์ data model์ ๋ค์์ ์ค์ํด์ผํฉ๋๋ค.
IdentifiableType
: ํ๋กํ ์ฝ์์ํด ์ ๊ณต๋identity
๋ ๊ทธ ๋ชจ๋ธ์ ์ธ์คํด์ค๋ฅผํ ์คํธ ๋ํํ๋ immutable(๋ณ๊ฒฝ๋ ์ ์๋) identifier์ ๋๋ค.Equatable
: RxDataSources๊ฐ ์ด๋ค cell์ด ๋ณํํ๋์ง ๊ฒฐ์ ํ๋ ๊ฒ์ ๋์์ค๋๋ค. ๊ทธ๋์ ์ด๋ฐ ์ ๋ค์ด animateํ ์ ์๊ฒํฉ๋๋ค.Car
model์ property์ ๋ณํ๊ฐ ์ ์ animated reload๋ฅผ ๋ฐ์์ํต๋๋ค.