Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios RxSwift订阅数据模型属性更改的正确方法_Ios_Swift_Mvvm_Rx Swift - Fatal编程技术网

Ios RxSwift订阅数据模型属性更改的正确方法

Ios RxSwift订阅数据模型属性更改的正确方法,ios,swift,mvvm,rx-swift,Ios,Swift,Mvvm,Rx Swift,这里是RxSwift的新成员。我有一个(MVVM)视图模型,它表示一个类似新闻提要的页面,订阅数据模型属性更改的正确方法是什么?在以下示例中,startUpdate()不断更新post。计算属性messageToDisplay和showldhart驱动一些UI事件 struct Post { var iLiked: Bool var likes: Int ... } class PostViewModel: NSObject { private var post

这里是RxSwift的新成员。我有一个(MVVM)视图模型,它表示一个类似新闻提要的页面,订阅数据模型属性更改的正确方法是什么?在以下示例中,
startUpdate()
不断更新
post
。计算属性
messageToDisplay
showldhart
驱动一些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
的每个属性和所有计算属性转换为
变量
?我觉得它不太合适。

//Class 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
}
static func请求(端点:String,查询:[String:Any]=[:])->可观察{
做{
guard let url=url(字符串:API)?.appendingPathComponent(端点)else{
抛出EOError.invalidURL(端点)
}
return manager.rx.responseJSON(.get,url)
.map({(响应,json)->[String:Any]在
guard let result=json作为?[String:Any]其他{
抛出EOError.invalidJSON(url.absoluteString)
}
返回结果
})
}抓住{
返回可观察的.empty()
}
}
静态var岗位:可观察={
返回NetworkRequest.request(端点:postEndpoint)
.map{中的数据
让posts=data[“post”]作为?[[String:Any]]??[]
返回岗位
.flatMap(Post.init)
.sorted{$0.name<$1.name}
}
.shareReplay(1)
}()
类PostViewModel:NSObject{
让posts=变量([])
设disposeBag=disposeBag()
重写func viewDidLoad(){
super.viewDidLoad()
帖子
.asObservable()
.subscribe(onNext:{[weak self]\uuIn
DispatchQueue.main.async{
//self?.tableView?.reloadData()如果要重新加载所有tableView
self.tableView.insertRows(位于:[indepath],带有:UITableViewRowAnimation.none)//或者如果要插入一行或多行。
//或更新用户界面
}
})
.处置(由:处置人)
posts.asObservable()
.bind(to:tableView.rx.items){[unowned self](tableView:UITableView,index:Int,element:Posts)在
让cell=tableView.dequeueReusableCell(标识符为“postCell”)作为!postCell
//例如,您需要使用textfield更新视图模型和单元格。如果您想使用单元格更新ui,请使用cell.button.tap{}。希望它对您有用。
cell.textField.rx.text
.orEmpty.asObservable()
.bind(到:self.posts.value[index].name!)
.处置(由:cell.disposeBag)
返回单元
}
startDownload()
}
}
func startDownload{
posts.value=NetworkRequest.posts
}

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

这如何解决我在post属性更改时更新UI的问题?when posts.value change posts.asObservable().subscribe(onNext:{[weak self]_uin将自动调用。这是observable或RXSwiftOk的主要功能,我看到了,所以我无法只更新
post
的单个属性,而是必须更新整个属性?请检查我更新的答案。您需要做的是先更新数组,然后使用下面的行,无需重新加载whole tableView.self.tableView.insertRows(位于:[IndexPath],带有:UITableViewRowAnimation.none)这就是如何找到您的IndexPath的方法,让IndexPath:IndexPath=IndexPath(行:(posts.count-1),节:0)