我正在測驗RxDataSources,它要求模型符合Equatableand IdentifiableType(類似于Identifiable協議。
我正在使用單向資料流來驅動 UI,我的模型是以下列舉:
enum ViewModelType: Equatable, IdentifiableType {
case loading
case post(Post)
var identity: String {
switch self {
case .loading: return "???" // <-- What to choose here?
case let .post(post): return String(post.id)
}
}
static func == (lhs: ViewModel.ViewModelType, rhs: ViewModel.ViewModelType) -> Bool {
switch (lhs, rhs) {
case (.loading, .loading): return true
case let (.post(l), .post(r)): return l == r
default: return false
}
}
}
}
關于.loadingViewModelType,如果我想一次使用這種型別的多個 ViewModelType[.loading, .loading, .loading]或差異中斷,我必須找到一個可能的穩定唯一識別符號identical identifier。
我準備了一個示例專案來重現該問題:https ://github.com/florianldt/RxDataSourcesIdentifiableType
我可以為這個用例找到任何可能的穩定唯一識別符號的想法。
uj5u.com熱心網友回復:
您需要進行一些更改,所有這些都源于您完全替換視圖模型而不考慮其先前狀態的事實。在構建狀態機時,請記住更新是基于輸入和之前的狀態。以下是您應該進行的最小更改:
無需構建自己的 AnimatableSectionModelType。只需使用庫提供的那個。用以下內容替換您的SingleSectionModel結構:
typealias SingleSectionModel<T> = AnimatableSectionModel<String, T> where T: IdentifiableType & Equatable
把你ViewModelType變成一個結構而不是一個列舉:
struct ViewModelType: Equatable, IdentifiableType {
let identity: UUID
let post: Post?
}
通過這樣做,您可以確保每個值都有一個標識。post您可以通過nil來判斷它正在“加載” 。
與其在每次更改狀態時完全替換您的視圖模型,不如使用其先前的狀態來幫助確定新狀態。這意味著洗掉您的init(state:)功能并添加這兩個功能:
func loading() -> ViewModel {
ViewModel(
state: .loading,
viewModels: [
ViewModelType(identity: UUID(), post: nil),
ViewModelType(identity: UUID(), post: nil),
ViewModelType(identity: UUID(), post: nil)
]
)
}
func loaded(posts: [Post]) -> ViewModel {
ViewModel(
state: .loaded,
viewModels: zip(viewModels, posts).map { ViewModelType(identity: $0.0.identity, post: $0.1) }
(posts.count > viewModels.count ? posts[viewModels.count...].map { ViewModelType(identity: UUID(), post: $0) } : [])
)
}
注意現在,所有三種視圖模型型別都有不同的身份,當帖子進來時,它們并沒有改變。那是關鍵。
當您獲取您的帖子時,您將需要使用視圖模型的先前狀態來進行更新:
private func fetchPosts() {
viewModel.accept(viewModel.value.loading())
Post.list()
.subscribe(onSuccess: { [viewModel] posts in
viewModel.accept(viewModel.value.loaded(posts: posts))
})
.disposed(by: disposeBag)
}
其余的變化應該很明顯。
uj5u.com熱心網友回復:
雖然我認為您不應該將資料源基于您正在加載的任何狀態(如果這些是唯一的帖子,請嘗試使用該帖子的 ID),但您始終可以使用UUID(或者,具體而言,UUID().uuidString用于唯一識別符號字串.
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/529559.html
標籤:迅速反应式编程不变性rx-swiftrxdatasources
上一篇:系結值只更改一次
