函数响应式编程思想 & RxSwift 核心逻辑

函数响应式编程 = 函数式编程 + 响应式编程

一、函数式

一种编程范式,如y=f(x)y=f(f(x))(高阶函数),不同的输入对应不同结果,f(x)对应具体的数据处理流程,可以是简单的常量值,也可以是复杂的计算或其他函数调用,x即为因变量,输入不同的x会输出不同的yC中的函数调用,OC中的方法调用,这种写法就叫做函数式编程。
特点:代码简洁(复用)、易于理解(接近自然语言)、便于代码管理。如代码:

eat().play().sleep()
sleep().eat().play()
play().eat()

一系列的动作简洁明了,相互不干扰,可以合并使用也可以分开单独使用。

二、响应式

对象对某一数据流变化做出响应的这种编码方式称为响应式。如对象A和对象BAB有一种“说不清”的关系,A要时刻监控B的行为,对B的变化也做出相应的变化。那么怎么实现呢?对于B来说,B做任何事都需要向A汇报,这样A就能实时监控B的行为,并响应。

在iOS开发中我们经常会响应一些事件buttontaptextFieldtextViewnotifactionKVONSTimer等等这些,都需要做响应监听,响应后都需要在对应的响应事件中去做处理,而原生开发中,触发对象与响应方法是分离的,如button的初始化和点击响应方法是分离的。如下:

override func viewDidLoad(){
    button = UIButton.init(frame: CGRect(x: 40, y: 100, width: width-80, height: 40))
    button.backgroundColor = .gray
    button.setTitle("按钮", for: .normal)
    self.view.addSubview(button)
    button.addTarget(self, action: #selector(clickBtn(button:)), for: .touchUpInside)
}
//button event
@objc func clickBtn(button:UIButton) {
    print("点击")
}

在代码量多的情况下,编写处理事件代码就不够直接,代码凌乱,需要联系上下文。如果将对象(button)和对应的响应方法(event)绑定在一起呢,如下:

override func viewDidLoad(){
    button = UIButton.init(frame: CGRect(x: 40, y: 100, width: width-80, height: 40))
    button.backgroundColor = .gray
    button.setTitle("按钮", for: .normal)
    self.view.addSubview(button)
    button.clickEvent = {(val)->Void in
        print("我被点击了")
    }
}

这样就很清晰了,对button要做的事一目了然。当然这里我对点击事件做了封装,事件在内部类触发,在内部button调用闭包,回调到当前button所实现的闭包中。除此之外,textfieldscrollviewtableview等事件通过闭包传值都可以封装成类似的写法。而这些简洁写法,在OCRACSwiftRxSwift都做了更好的封装,这种编程思想便称为函数响应式编程思想。

三、RxSwift介绍

全称ReactiveX for Swift,是一个简化异步编程的框架,实现了函数响应式编程,事件与对象紧密联系,业务流清晰,便于管理。在RxSwift中,所有异步操作(事件)和数据流均被抽象为可观察序列的概念。流程:

创建序列 -> 订阅序列 -> 发送信号 -> 信号接收

对象的创建到事件监听一气呵成。下面看一段代码感受一下:

override func viewDidLoad() {
    super.viewDidLoad()
    //button
    button = UIButton.init(frame: CGRect(x: 40, y: 100, width: width-80, height: 40))
    button.backgroundColor = .gray
    button.setTitle("按钮", for: .normal)
    self.view.addSubview(button)
    //修改事件类型 button.rx.controlEvent(.touchUpOutside)
    button.rx.tap.subscribe(onNext: { () in
        //此处响应点击事件
        print("我被点击了")
    }).disposed(by: disposeBag)
    
    //textfield
    textfield = UITextField.init(frame: CGRect(x: 40, y: 200, width: width-80, height: 40))
    textfield.borderStyle = .roundedRect
    textfield.placeholder = "请输入内容"
    self.view.addSubview(textfield)
    //监听输入变化
    textfield.rx.text.orEmpty.changed.subscribe(onNext: { (text) in
        print(text)
    }).disposed(by: disposeBag)
}

每一个对象将可监听序列绑定到观察者上(对象本身),独立在自己的一块区域。咋一看太爽了,不用写事件方法(或代理方法)了,直接在闭包回调中就可以处理响应事件。

顿时感觉人生观被颠覆了,事件还可以这么写!!!再也不用联系上下文了

四、RxSwift简单使用

Rx多用于事件响应绑定,绑定到button上、手势、输入框、KVO、代理等等。在OC开发中我也经常对这些事件封装,与对象绑定,使之形影不离,代码简洁,结构清晰,代码量少,非常好用,自从看到RACRxSwift发现自己的那些工作量,哎!,相见恨晚。下面就来体验一下Rx的使用:

1、button点击事件

//修改事件类型 button.rx.controlEvent(.touchUpOutside)
button.rx.tap.subscribe(onNext: { () in
    print("被点击了")
    //处理事件 ……
}).disposed(by: disposeBag)

2、手势点击事件

let tap = UITapGestureRecognizer.init()
self.view.addGestureRecognizer(tap)
tap.rx.event.subscribe(onNext: { (tap) in
    print(tap.view as Any)
    //处理事件 ……
}).disposed(by: disposeBag)

3、输入框监听输入事件

//监听输入变化
textfield.rx.text.orEmpty.changed.subscribe(onNext: { (text) in
    print(text)
    //处理事件 ……
}).disposed(by: disposeBag)
//绑定,数据传递
textfield.rx.text.bind(to: label.rx.text)

天呐!这个居然还能绑定!!

4、KVO事件监听

self.person.rx.observeWeakly(String.self, "name").subscribe(onNext: { (value) in
    print(value as Any)
    //处理事件 ……
}).disposed(by: disposeBag)

5、监听滑动事件

scrollview.rx.contentOffset.subscribe(onNext: { [weak self](content) in
    let y = content.y
    print(content.y)
    //处理事件 ……
}).disposed(by: disposeBag)

6、定时器应用 - 定时1秒响应一次

let timer = Observable<Int>
    .interval(1, scheduler: MainScheduler.instance)
timer.subscribe(onNext: { (time) in
        print(time)
        //处理事件 ……
    }).disposed(by: disposeBag)

这种骚操作吓得我不敢说话了,用就是了~

7、键盘通知

NotificationCenter.default.rx
.notification(UIResponder.keyboardWillShowNotification)
    .subscribe(onNext: { (notification) in
        //获取值
        let during = notification.userInfo?["UIKeyboardAnimationDurationUserInfoKey"] as? Float
        print(during!)
        //处理事件 ……
    }).disposed(by: disposeBag)

8、网络请求

let url = URL.init(string: "https://www.baidu.com")
URLSession.shared.dataTask(with: url!) { (data, response, error) in
    print("network")
    print(String.init(data: data!, encoding: .utf8))
}.resume()
URLSession.shared.rx.response(request: URLRequest.init(url: url!))
    .subscribe(onNext: { (data) in
        print(data)
    }, onError: { (error) in
        print(error)
    }, onCompleted: {
        print("请求完成")
    }).disposed(by: disposeBag)

……
还有很多这种事件绑定就不一一列出了,自己使用自己体会。

五、RxSwift核心

凡事物皆序列,如scrollview滑动的距离 10、20、30、40 ……就构成了一个序列,设置在100处做出改变。

scroll.png

通过以上的介绍和示例,RxSwift实现逻辑感觉很清晰了,说多了自己都烦,赶紧用起来。直接上一个总结图,偷来的🤠:

sequence.png

有个老铁这块源码分析写的很清楚,我偷懒了:
https://www.jianshu.com/p/c9f854718933
RxSwift核心源码探索

RxSwift中文文档
RxSwift-github
ReactiveX系列

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