OGeek|极客世界-中国程序员成长平台

标题: ios - RxSwift 订阅数据模型属性更改的正确方法 [打印本页]

作者: 菜鸟教程小白    时间: 2022-12-11 19:50
标题: ios - RxSwift 订阅数据模型属性更改的正确方法

这里是 RxSwift 的新手。我有一个(MVVM) View 模型,它代表一个类似新闻源的页面,订阅数据模型属性更改的正确方法是什么?在以下示例中,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?我觉得不太对劲。



Best Answer-推荐答案


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

如果您想更改任何内容,请使用 subscribe、bind、concat .. 您可以使用许多方法和属性。

关于ios - RxSwift 订阅数据模型属性更改的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49212915/






欢迎光临 OGeek|极客世界-中国程序员成长平台 (http://ogeek.cn/) Powered by Discuz! X3.4