RxSwift 入门练习总结

demo.gif

使用的第三方库

target 'WeatherDemo_RxSwift' do

  use_frameworks!

  pod 'RxSwift', '~> 3.5.0'
  pod 'RxCocoa', '~> 3.5.0'
  pod 'RxDataSources', '~> 1.0.4'
  
end

1.所有的控制器都加上析构函数,以方便查看是否有循环引用

deinit {
        print("\(self) 释放")
 }

2.按钮订阅点击事件

tapButton.rx.tap
            .subscribe({ [unowned self] _ in
                let numStr : String = self.numberLabel.text!
                let number = Int(numStr)
                self.numberLabel.text = String(number! + 1)
            
            }).addDisposableTo(disposeBag)

注意: 一定要加[unowned self],或者[weak self]否则会出现循环引用,关于它俩的使用情况,参考@ONEVCAT内存管理,WEAK 和 UNOWNED

3.订阅手势事件,给按钮添加长按手势

let longPressGesture = UILongPressGestureRecognizer()
longPressGesture.rx.event
            .subscribe(onNext: { [unowned self] _ in
            
                let numStr : String = self.numberLabel.text!
                let number = Int(numStr)
                self.numberLabel.text = String(number! + 1)
                
            }).addDisposableTo(disposeBag)
self.tapButton.addGestureRecognizer(longPressGesture)

此处,用了subscribe.onNext.注意:onNext 只监听sequence发出的next事件中的element进行处理,他会忽略error和completed事件

疑问点:大部分情况subscribe 硬敲出来的 为啥代码没有自动补全???

4.结合tableView,Variable使用示例

// Variable流,初始值字符串数组
let items = Variable(["Mike",
                    "Apples",
                    "Ham",
                    "Eggs"])

let items2 = [
            "Fish",
            "Carrots",
            "Mike",
            "Apples",
            "Ham",
            "Eggs",
            "Bread",
            "Chiken",
            "Water"
        ]

// Variable使用必须要加asObservable
// 数据流绑定到tableView 
items.asObservable()
            .bind(to: tableView.rx.items(cellIdentifier: "Cell",cellType:UITableViewCell.self),curriedArgument: { (row, element, cell) in
                cell.textLabel?.text = element
            }).addDisposableTo(disposeBag)

// 原生的refresh
refreshControl.rx.controlEvent(.valueChanged)
        .subscribe(onNext: { [unowned self] _ in
          // 更改Variable.value 模拟刷新
            items.value = items2
            self.refreshControl.endRefreshing()
        }).addDisposableTo(disposeBag)
        
tableView.addSubview(refreshControl)
知识点:
  • 要理解Variable,需要先理解Subject,Subjet是observable和Observer之间的桥梁,一个Subject既是一个Obserable也是一个Observer,他既可以发出事件,也可以监听事件
  • BehaviorSubject : 当你订阅了BehaviorSubject,你会接受到订阅之前的最后一个事件
  • Variable是BehaviorSubject一个包装箱,就像是一个箱子一样,使用的时候需要调用asObservable()拆箱,里面的value是一个BehaviorSubject,他不会发出error事件,但是会自动发出completed事件

5.逆向传值,代理使用示例

// 代理声明 必须要继承 class 否则报错
protocol DataEnteredDelegate: class {
    func userDidEnterInformation( info: String )
}

// 代理声明必须要weak,防止循环引用
weak var delegate : DataEnteredDelegate? = nil

// 监听键盘右下角done事件,调用代理方法
@IBAction func textOnExit(_ sender: Any) {
    delegate?.userDidEnterInformation(info: textField.text!)
    self.navigationController?.popViewController(animated: true)
}
知识点:
  • 需要把protocol 限制在 class 内,这是因为 Swift 的 protocol 是可以被除了 class 以外的其他类型遵守的, 而对于像 struct 或是 enum 这样的类型,本身就不通过引用计数来管理内存,所以也不可能用 weak 这样的 ARC 的概念来进行修饰
    王巍 (@ONEVCAT) delegate

6. 第三方RxDataSources使用示例

// 1.数据流 just用法
let items = Observable.just([
        SectionModel(model: "B",items:[
            "Barbara Cole",
            "Barbara Cooper",
            "Barbara Diaz",
            "Barbara Edwards",
            "Barbara Garcia",
            "Barbara Gray",
            "Barbara Griffin",
            "Barbara Hill",
            "Barbara Howard",
            "Barbara Hughes"
            ]),
        SectionModel(model:"C",items:[
            "Carol Lopez", "Carol Lopez"
            ]),
        SectionModel(model: "E", items: [
            "Elizabeth Jenkins", "Elizabeth Kelly"
            ]),
        SectionModel(model: "H", items: ["Helen Anderson", "Helen Bailey", "Helen Cole", "Helen Cox"]),
        SectionModel(model: "J", items: ["James Anderson", "James Barnes", "James Bell"]),
        SectionModel(model: "K", items: ["Karen Green", "Karen Jenkins", "Karen Jones", "Karen Jordan"]),
        SectionModel(model: "L", items: ["Linda Taylor", "Linda Taylor", "Linda Torres", "Linda West", "Lisa Brooks"]),
        SectionModel(model: "M", items: ["Margaret Bell", "Margaret Coleman", "Margaret Cox", "Margaret Foster"]),
        SectionModel(model: "R", items: ["Robert Clark", "Robert Coleman", "Robert Cook", "Robert Cook"]),
        SectionModel(model: "S", items: ["Susan Fisher", "Susan Ford", "Susan Ford", "Susan Hernandez", "Susan Howard"]),
        ])

// 2.创建数据源 类型<String,String>
let dataSource = RxTableViewSectionedReloadDataSource<SectionModel<String,String>>()

// 3. dataSources配置cell
fileprivate func setupDataSource() {
        
        // 参数必须4个,_占位用
        dataSource.configureCell =  { (_,tableView,IndexPath,element) in
            let cell = tableView.dequeueReusableCell(withIdentifier: "Cell")!
            cell.textLabel?.text = element
            return cell
        }
        
        // 监听右侧边缘小字母点击事件
        dataSource.sectionForSectionIndexTitle = { (dataSource,title,index) -> Int in
            print("\(index)")
            return index
        }
        
        dataSource.sectionIndexTitles = { data -> [String]? in
            return data.sectionModels.map{ $0.model }
        }
    }

//  4. 数据流items,绑定到dataSource上
 items.bind(to: tableView.rx.items(dataSource: dataSource))

// 5. 设置tableView代理
 _ = tableView.rx.setDelegate(self)

7. 自定义可观察序列create 示例

//  create 自定义可观察序列 返回的WeatherData 类型流
     func fetchWeatherData() -> Observable<WeatherData> {
        let observable = Observable<WeatherData>.create { [weak self] observer in
            if let weakSelf = self{
                let time = 0.5 + TimeInterval(arc4random_uniform(10)) / 10.0
                
                // 主线程延迟处理,模拟网络请求数据
                DispatchQueue.main.asyncAfter(deadline: .now() + time, execute: { 
                    let shouldFail = arc4random_uniform(2) == 0
                    if shouldFail {
                        observer.onError(NSError(domain:"Fake network error", code: 0, userInfo: nil))
                    }else{
                        observer.onNext(weakSelf.createRandomWeatherData())
                        observer.onCompleted()
                    }
                    
                })
            }
            return Disposables.create() // 固定写法,记住 需实现.onError() .onNext .onCompleted
        }
        return observable.shareReplay(1)
    }
// 建议使用addDisposableTo
self.viewModel.locationName.drive(self.locationLabel.rx.text).addDisposableTo(disposeBag)

// 而不是用 disposed(by: disposeBag)
self.viewModel.locationName.drive(self.locationLabel.rx.text).disposed(by: disposeBag)

// 按钮tap事件建议使用subscribe
button.rx.tap
            .subscribe(onNext:{
                [unowned self] in
                let selectedDate = dateFormatter.string(from: self.datePicker.date)
                self.title = selectedDate
            }).addDisposableTo(disposeBag)

// 而不是用bind
button.rx.tap
            .bind { [unowned self] in
                let selectedDate = dateFormatter.string(from: self.datePicker.date)
                self.title = selectedDate
        }.addDisposableTo(disposeBag)

RxSwift概念理解
RxSwift学习资料,内涵很多RxSwift开源项目
本示例下载

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容

  • 发现 关注 消息 RxSwift入坑解读-你所需要知道的各种概念 沸沸腾关注 2016.11.27 19:11*字...
    枫叶1234阅读 2,765评论 0 2
  • 本文章内部分图片资源来自RayWenderlich.com 本文结合自己的理解来总结介绍一下RxSwift最基本的...
    FKSky阅读 2,845评论 4 14
  • //PublishSubject -> 会发送订阅者从订阅之后的事件序列 PublishSubjectlet se...
    zidon阅读 1,552评论 0 3
  • 寻寻觅觅不知冬夏 兜兜转转不知真假 我们冲空旷歇斯底里 听声音消失在眼下 褪去层层天真的伤疤 披上块块成熟的铠甲 ...
    风蓬非悲歌阅读 214评论 0 2
  • 俗语云:花无百日红,人无百日好。或许每天的快节奏生活,令我不得不因病做手术,使生活得以慢下脚步,手术...
    一揽阳光阅读 169评论 0 3