[英]RxSwift correct way to subscribe to data model property change
New to RxSwift here. 这里是RxSwift的新功能。 I have a (MVVM) view model that represents a Newsfeed-like page, what's the correct way to subscribe to change in data model's properties?
我有一个(MVVM)视图模型,该视图模型表示类似Newsfeed的页面,订阅数据模型属性更改的正确方法是什么? In the following example,
startUpdate()
constantly updates post
. 在以下示例中,
startUpdate()
不断更新post
。 The computed properties messageToDisplay
and shouldShowHeart
drives some UI event. 计算的属性
messageToDisplay
和shouldShowHeart
驱动一些UI事件。
struct Post {
var iLiked: Bool
var likes: Int
...
}
class PostViewModel: NSObject {
private var post: Post
var messageToDisplay: String {
if post.iLiked { return ... }
else { return .... }
}
var shouldShowHeart: Bool {
return iLiked && likes > 10
}
func startUpdate() {
// network request and update post
}
...
}
It seems to me in order to make this whole thing reactive, I have to turn each properties of Post
and all computed properties into Variable
? 在我看来,为了使整个过程具有反应性,我必须将
Post
每个属性和所有计算的属性转换为Variable
? It doesn't look quite right to me. 在我看来,这不太正确。
// Class NetworkRequest or any name //类NetworkRequest或任何名称
static func request(endpoint: String, query: [String: Any] = [:]) -> Observable<[String: Any]> {
do {
guard let url = URL(string: API)?.appendingPathComponent(endpoint) else {
throw EOError.invalidURL(endpoint)
}
return manager.rx.responseJSON(.get, url)
.map({ (response, json) -> [String: Any] in
guard let result = json as? [String: Any] else {
throw EOError.invalidJSON(url.absoluteString)
}
return result
})
} catch {
return Observable.empty()
}
}
static var posts: Observable<[Post]> = {
return NetworkRequest.request(endpoint: postEndpoint)
.map { data in
let posts = data["post"] as? [[String: Any]] ?? []
return posts
.flatMap(Post.init)
.sorted { $0.name < $1.name }
}
.shareReplay(1)
}()
class PostViewModel: NSObject {
let posts = Variable<[Post]>([])
let disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
posts
.asObservable()
.subscribe(onNext: { [weak self] _ in
DispatchQueue.main.async {
//self?.tableView?.reloadData() if you want to reload all tableview
self.tableView.insertRows(at: [IndexPath], with: UITableViewRowAnimation.none) // OR if you want to insert one or multiple rows.
//OR update UI
}
})
.disposed(by: disposeBag)
posts.asObservable()
.bind(to: tableView.rx.items) { [unowned self] (tableView: UITableView, index: Int, element: Posts) in
let cell = tableView.dequeueReusableCell(withIdentifier: "postCell") as! PostCell
//for example you need to update the view model and cell with textfield.. if you want to update the ui with a cell then use cell.button.tap{}. hope it works for you.
cell.textField.rx.text
.orEmpty.asObservable()
.bind(to: self.posts.value[index].name!)
.disposed(by: cell.disposeBag)
return cell
}
startDownload()
}
}
func startDownload {
posts.value = NetworkRequest.posts
}
If you want to change anything then use subscribe, bind, concat .. There are many methods and properties which you can use. 如果要更改任何内容,请使用subscription,bind,concat ..您可以使用许多方法和属性。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.