美文网首页IOS 超级无敌程序员iOS大咖说
Swift - RxSwift的使用详解2(响应式编程与传统式编

Swift - RxSwift的使用详解2(响应式编程与传统式编

作者: 八级大狂风AM | 来源:发表于2018-03-07 17:50 被阅读803次

    在详细介绍 RxSwift 相关的知识点之前,我想先通过一个样例演示下 RxSwift 到底能做什么,好让大家能够对其有一个直观的了解。

    三、两种编程方式的比较样例

    1,效果图

    这里我以最常见的 tableView 数据展示功能为例作为演示。后面分别使用传统写法,以及使用 RxSwift 响应式写法来实现,大家可以比较下它们的区别。

    •     表格中显示的是歌曲信息(歌名,以及歌手)
    •     点击选中任意一个单元格,在控制台中打印出对应的歌曲信息。

    2,准备工作

    首先我们创建一个 Music 的结构体,用来保存歌曲名称、歌手名字。此外它还遵循 CustomStringConvertible 协议,方便我们输出调试。

    import UIKit
     
    //歌曲结构体
    struct Music {
        let name: String //歌名
        let singer: String //演唱者
         
        init(name: String, singer: String) {
            self.name = name
            self.singer = singer
        }
    }
     
    //实现 CustomStringConvertible 协议,方便输出调试
    extension Music: CustomStringConvertible {
        var description: String {
            return "name:\(name) singer:\(singer)"
        }
    }
    

    3,过去我们会这么做(传统式编程)

    (1)首先写一个 ViewModel

    • 这里面没有什么太复杂的东西,就是生成一个 UITableView 所使用的数据源。
    import Foundation
     
    //歌曲列表数据源
    struct MusicListViewModel {
        let data = [
            Music(name: "无条件", singer: "陈奕迅"),
            Music(name: "你曾是少年", singer: "S.H.E"),
            Music(name: "从前的我", singer: "陈洁仪"),
            Music(name: "在木星", singer: "朴树"),
        ]
    }
    

    (2)视图控制器代码(ViewController.swift)

    • 接着我们设置 UITableView 的委托,并让视图控制器实现 UITableViewDataSourceUITableViewDelegate 协议,及相关的协议方法。
    • 这个大家肯定都写过无数遍了,也没什么好讲的。算一下,这里一共需要 43 行代码。
    import UIKit
    import RxSwift
     
    class ViewController: UIViewController {
     
        //tableView对象
        @IBOutlet weak var tableView: UITableView!
         
        //歌曲列表数据源
        let musicListViewModel = MusicListViewModel()
         
        override func viewDidLoad() {
            super.viewDidLoad()
             
            //设置代理
            tableView.dataSource = self
            tableView.delegate = self
        }
    }
     
    extension ViewController: UITableViewDataSource {
        //返回单元格数量
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return musicListViewModel.data.count
        }
         
        //返回对应的单元格
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath)
            -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: "musicCell")!
            let music = musicListViewModel.data[indexPath.row]
            cell.textLabel?.text = music.name
            cell.detailTextLabel?.text = music.singer
            return cell
        }
    }
     
    extension ViewController: UITableViewDelegate {
        //单元格点击
        func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
            print("你选中的歌曲信息【\(musicListViewModel.data[indexPath.row])】")
        }
    }
    

    4,现在使用 RxSwift 进行改造(响应式编程)

    (1)对 ViewModel 做些修改

    • 这里我们将 data 属性变成一个可观察序列对象(Observable Squence),而对象当中的内容和我们之前在数组当中所包含的内容是完全一样的。
    • 关于可观察序列对象在后面的文章中我会详细介绍。简单说就是“序列”可以对这些数值进行“订阅(Subscribe)”,有点类似于“通知(NotificationCenter)
    import RxSwift
     
    //歌曲列表数据源
    struct MusicListViewModel {
        let data = Observable.just([
            Music(name: "无条件", singer: "陈奕迅"),
            Music(name: "你曾是少年", singer: "S.H.E"),
            Music(name: "从前的我", singer: "陈洁仪"),
            Music(name: "在木星", singer: "朴树"),
        ])
    }
    

    (2)视图控制器代码(ViewController.swift)

    • 这里我们不再需要实现数据源和委托协议了。而是写一些响应式代码,让它们将数据和 UITableView 建立绑定关系。
    • 算了下这里我们只需要 31 行代码,同之前的相比,一下减少了 1/4 代码量。而且代码也更清爽了些。

    代码的简单说明:

    • DisposeBag:作用是 Rx 在视图控制器或者其持有者将要销毁的时候,自动释法掉绑定在它上面的资源。它是通过类似“订阅处置机制”方式实现(类似于 NotificationCenterremoveObserver)。
    • rx.items(cellIdentifier:):这是 Rx 基于 cellForRowAt 数据源方法的一个封装。传统方式中我们还要有个 numberOfRowsInSection 方法,使用 Rx 后就不再需要了(Rx 已经帮我们完成了相关工作)。
    • rx.modelSelected: 这是 Rx 基于 UITableView委托回调方法 didSelectRowAt 的一个封装。
    import UIKit
    import RxSwift
    import RxCocoa
     
    class ViewController: UIViewController {
     
        //tableView对象
        @IBOutlet weak var tableView: UITableView!
         
        //歌曲列表数据源
        let musicListViewModel = MusicListViewModel()
         
        //负责对象销毁
        let disposeBag = DisposeBag()
         
        override func viewDidLoad() {
            super.viewDidLoad()
             
            //将数据源数据绑定到tableView上
            musicListViewModel.data
                .bind(to: tableView.rx.items(cellIdentifier:"musicCell")) { _, music, cell in
                    cell.textLabel?.text = music.name
                    cell.detailTextLabel?.text = music.singer
                }.disposed(by: disposeBag)
             
            //tableView点击响应
            tableView.rx.modelSelected(Music.self).subscribe(onNext: { music in
                print("你选中的歌曲信息【\(music)】")
            }).disposed(by: disposeBag)
        }
    }
    

    RxSwift使用详解系列
    原文出自:www.hangge.com转载请保留原文链接

    相关文章

      网友评论

      • 东也_:我就更尴尬了 viewmodel的data.count根本敲不出来 data就不是个数组 还有那个闭包我也是跟大家说的那样没有提示
      • Self_Time:实用简洁,不过写tableView还是老老实实写,业务层的东西毕竟复杂一点。很棒!
      • 糊涂0:按照这个写出来,跑不起来,一跑报错!
        zhao先生_89:@糊涂0 代码贴出来看下
        糊涂0:@zhao先生_89 注册了,没有用 ! Fatal error: Failure converting from Optional(<HVipApp.HSRxSwiftViewController: 0x7f967b5282a0>) to UIScrollViewDelegate: file /Users/xuzhao/Desktop/HVipApp/Pods/RxCocoa/RxCocoa/RxCocoa.swift, line 150
        (lldb)
        zhao先生_89:cell需要提前注册
      • 你大赟哥:请问,大佬,这个必报直接敲出来的么,?怎样才能有提示呢?
      • Cooci_和谐学习_不急不躁:大佬: 这里我们不再需要实现数据源和委托协议了。
        tableView.delegate = self;
        tableView.dataSource = self; 这两句不报错?
        musicListVM.data.bind(to: tableView.rx.items(cellIdentifier: "cell")){_,music,cell in
        cell.textLabel?.text = music.name
        cell.detailTextLabel?.text = music.singer
        }.disposed(by: disposeBag) 你是硬敲?
      • 书包里的码农:大佬你好,这里有一句我不明白
        musicListVM.data.bind(to: tableView.rx.items(cellIdentifier: "cell")){_,music,cell in
        cell.textLabel?.text = music.name
        cell.detailTextLabel?.text = music.singer
        }.disposed(by: disposeBag)
        这里闭包里面的参数是怎么来的{_,music,cell in},闭包也是直接敲出来的,正常的话闭包应该是一个方法的参数,是可以直接提示出来的啊.
        zhao先生_89:@cassiel社长 我也显示不出来,没有地方去指定创建cell时的style。可以自定义cell
        糊涂0:我也敲不出来!没有提示的!大佬你最后强行敲出来了吗??
        郁金社长:为啥我的detailTextLabel上的text显示不出来?

      本文标题:Swift - RxSwift的使用详解2(响应式编程与传统式编

      本文链接:https://www.haomeiwen.com/subject/xyphfftx.html