はじめに
RxSwiftで、TableViewの差分更新を行うときに、RxDataSourcesを使うことがあると思います。
RxDataSorcesの詳細に関しては、公式レポジトリーを参照してださい....
RxDataSources
RxTableViewSectionedAnimatedDataSourceを使う場合、AnimatableSectionModelTypeに準拠したmodelを用意する必要があります。
実装としては
-
RxTableViewSectionedAnimatedDataSourceでcellやsectionなどのtableViewの設定をAnimatableSectionModelTypeに準拠したmodelを用いて行う -
AnimatableSectionModelTypeに準拠したObservableなmodelをtableViewにbindする
詳細はサンプルコードをみてください。(RxDataSources/Example/Example1_CustomizationUsingTableViewDelegate.swift)
Equatableへの準拠
上記の実装のように、RxDataSourcesを使うにはAnimatableSectionModelTypeに準拠したmodelを用意する必要があり、準拠するAnimatableSectionModelTypeのprotocolは下記のようになっています。
public protocol AnimatableSectionModelType {
: SectionModelType
, IdentifiableType where Item: IdentifiableType, Item: Equatable {
}
また、AnimatableSectionModelTypeが準拠しているSectionModelTypeは下記の実装になっています。
public protocol SectionModelType {
associatedtype Item
var items: [Item] { get }
init(original: Self, items: [Item])
}
SectionModelTypeのGenericsのItemはIdentifiableTypeとEquatableに準拠する必要があります!!
困ったこと:Equatableに準拠できない!?
NSObjectに準拠したmodelをEquatableに準拠させようとしていた。。。
class TestModel: NSObject {
let id: Int
}
extension TestModel: Equatable {
static func == (lhs: TestModel, rhs: TestModel) -> Bool {
return lhs.id == rhs.id
}
}
下記のコンパイルエラーがでる
Redundant conformance of 'TestModel' to protocol 'Equatable'
自作したクラスTestModelをEquatableに準拠したつもりはないのに、なぜ準拠済みなのかわからない??
理由:NSObjectがすでにEquatableである!
NSObjectのドキュメントのConformsにあるように、NSObjectはすでにEquatableに準拠しています。そのため、上記の実装だと既に準拠だとエラーが出ます。
ちなみに、NSObjectのEquatableは参照しているポインタが同じかどうかをチェックしています。
superクラスの比較でなく、subclassを用いて比較させたい場合は、subclassにクラスメソッドを実装することで、subclassでの比較を行うことができます。
extension TestModel {
static func ==(lhs: TestModel, rhs: TestModel) -> Bool {
return lhs.id == rhs.id
}
}
swift4.1からのEquatable
ここからは上記のエラーとは異なりますが、Equatableなクラスを実装するときの追加の話です。
swift4.1からは、より簡単にEquatableの実装を行うことができます。
swift4.1で実装されたSynthesizing Equatable and Hashable conformanceによって、コンパイラーが自動的にEquatableとHashableに準拠させてくれます。
条件としては、
Equatableの実装するクラス or enum or structで定義されているstored instance propertyとassociated valueが、Equatableに準拠している場合に、static func == (lhs: Self, rhs: Self) -> Boolが暗黙的に実装されます。
実装例が下記になります!
swift4.0の場合
struct Person: Equatable {
let firstName: String
let lastName: String
static func == (lhs: Person, rhs: Person) -> Bool {
return lhs.firstName == rhs.firstName &&
lhs.lastName == rhs.lastName &&
}
}
swift4.1の場合(暗黙的にEquatableに準拠できる!!)
struct Person: Equatable {
let firstName: String
let lastName: String
}
上記のようにEquatableに準拠する際に、大量のコードを記述する必要がなくなって、よりEquatableが使いやすくなり、RxDataSourcesも使いやすくなったと思います!!!