簡體   English   中英

RxSwift訂閱數據模型屬性更改的正確方法

[英]RxSwift correct way to subscribe to data model property change

這里是RxSwift的新功能。 我有一個(MVVM)視圖模型,該視圖模型表示類似Newsfeed的頁面,訂閱數據模型屬性更改的正確方法是什么? 在以下示例中, startUpdate()不斷更新post 計算的屬性messageToDisplayshouldShowHeart驅動一些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
    }
    ...
}

在我看來,為了使整個過程具有反應性,我必須將Post每個屬性和所有計算的屬性轉換為Variable 在我看來,這不太正確。

//類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
}

如果要更改任何內容,請使用subscription,bind,concat ..您可以使用許多方法和屬性。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM