博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ReactiveCocoa使用
阅读量:7100 次
发布时间:2019-06-28

本文共 7603 字,大约阅读时间需要 25 分钟。

在ReactiveCocoa 5.0之前

看了简书上的一篇文章,

ReactiveSwift和ReactiveCocoa。

ReactiveSwift

官方原文: ReactiveSwift offers composable, declarative and flexible primitives that are built around the grand concept of streams of values over time. These primitives can be used to uniformly represent common Cocoa and generic programming patterns that are fundamentally an act of observation.Because all of these different mechanisms can be represented in the same way, it’s easy to declaratively chain and combine them together, with less spaghetti code and state to bridge the gap. 总的来说就是ReactiveSwift提供了可组合的、声明式的和灵活的基本类型。归结为以下6大类:

委托方法(Delegate methods) 回调函数块(Callback blocks) 通知(Notifications) 控制动作和响应者链事件(Control actions and responder chain events) 将来和承诺(Futures and promises) 键值观察(Key-value observing (KVO) 因为这些所有不同的机制都可以用同一种方式来表达,使用基本类型更容易地进行链式编程,通过把它们结合在一起,减少了套管程序(spaghetti code)。

ReactiveCocoa

官方原文: ReactiveCocoa wraps various aspects of Cocoa frameworks with the declarative ReactiveSwift primitives. ReactiveCocoa使用ReactiveSwift的基本类型来封装Cocoa框架的方方面面。

介绍完了ReactiveSwift和ReactiveCocoa,下面我们就开始学习吧。

我们要实现 一个登录的页面,输入用户名user和password密码就可以登录啦,登录成功之后

1、打开你的终端,cd到项目目录,接着输入以下命令:

pod init 复制代码

2.文本文件打开编辑

target 'RacSwift' do  # Comment the next line if you're not using Swift and don't want to use dynamic frameworks  use_frameworks!        pod 'ReactiveCocoa'end复制代码

3.保存退出,cd到根目录,执行

pod install复制代码

安装成功

打开ViewController,导入import ReactiveCocoa 在viewdidload方法中添加账户输入窗

绘制界面 创建vc成员变量

var accountTextfield = UITextField();  var passWordTextfield = UITextField();  var loginBtn = UIButton();复制代码

在viewdidload初始化

accountTextfield = UITextField.init(frame:CGRect.init(x: 100, y: 200, width: 200, height: 50));        self.view.addSubview(accountTextfield);        accountTextfield.placeholder = "输入账户名"                accountTextfield.backgroundColor = UIColor.lightGray;        passWordTextfield = UITextField.init(frame:CGRect.init(x: 100, y: 300, width: 200, height: 50));        self.view.addSubview(passWordTextfield);        passWordTextfield.placeholder = "输入密码"                passWordTextfield.backgroundColor = UIColor.lightGray;                loginBtn = UIButton.init(frame: CGRect.init(x: 150, y: 380, width: 100, height: 40))                self.view.addSubview(loginBtn);                loginBtn.backgroundColor = UIColor.gray;        loginBtn.setTitle("login", for: .normal);                loginBtn.title(for: .normal);        loginBtn.layer.cornerRadius = 3.0;        loginBtn.layer.masksToBounds = true;复制代码

添加方法:

accountTextfield.reactive.continuousTextValues.observeValues { (account) in                    };复制代码

运行后输入Qwertyuiop,控制台输出如下:

QQwQweQwerQwertQwertyQwertyuQwertyuiQwertyuioQwertyuiop复制代码

此时是不是体会到RAC的强大了,我们并没有添加监听或者实现委托代理,就可以达到输入的监听效果。 这里简单分析一下 输入过程中,ReactiveCocoa信号会发送一系列的事件给订阅者(观察者)。

ReactiveCocoa有以下事件:

  • Value事件:Value事件提供了新值

  • Failed事件:Failed事件表明在信号完成之前发生了错误

  • Completed事件:Completed事件信号完成了,之后不会再有新的值发送

  • Interrupted事件:Interrupted事件表明由于被取消,信号被终止了

accountTextfield.reactive就是把accountTextfield变成可响应的,而continuousTextValues就是account值的信号。通过observeValues,我们可以观察到continuousTextValues这个信号传来的Value事件,每次在accountTextfield输入的时候,我们就会接收到text的值。

使用filter,将代码修改如下

accountTextfield.reactive.continuousTextValues.filter({            text in                        return text!.reversed().count > 4        }).observeValues {            text in                        print(text ?? "")        }复制代码

输入Qwertyuiop,可以看到控制台输出

QwertQwertyQwertyuQwertyuiQwertyuioQwertyuiop复制代码

filter这个函数只允许当它的返回值为true的事件发生,在这里是输入的字符数大于4个,也就是说字符数小于等于4的事件会被过滤掉。

继续添加如下方法

accountTextfield.reactive.continuousTextValues.map({            text in                        return text!.reversed().count        }).filter({            characterCount in                        return characterCount > 2        }).observeValues {            characterCount in                        print(characterCount ?? "")        }复制代码

输入Qwertyuiop,控制台输出:

3Qwer4Qwert5Qwerty6Qwertyu7Qwertyui8Qwertyuio9Qwertyuiop10复制代码

新添加的map函数,给map函数提供一个closure,它就能够转换事件的数据。对于每一次map接收到的Value事件,它就会运行closure,以closure的返回值作为Value事件发送出去。上面的代码中,我们的text的值映射成text的字符数,这个方法与filter方法通知执行。 加入密码框

let passWordTextfield = UITextField.init(frame:CGRect.init(x: 100, y: 300, width: 200, height: 50));        self.view.addSubview(passWordTextfield);        passWordTextfield.placeholder = "输入密码"                passWordTextfield.backgroundColor = UIColor.lightGray;复制代码

创建合法状态的信号

//验证手机号 func isAccount()->Bool{        if accountTextfield.text == account {            return  true;        }else{                        return false;        }    }// 验证密码    func isPassword()->Bool{        if passWordTextfield.text == pass {            return  true;        }else{                        return false;        }    }复制代码

在viewdidload添加信号映射

accountTextfield.reactive.continuousTextValues.map {            text in                        return self.isAccount()        }passWordTextfield.reactive.continuousTextValues.map{                        text in            return self.isPassword()        }复制代码

上述两个方法已经完成了监听

let validUsernameSignal = accountTextfield.reactive.continuousTextValues.map({            text in                        return self.isAccount()        })                validUsernameSignal.map({            isValidUsername in                        return isValidUsername ? UIColor.red : UIColor.yellow        }).observeValues {            backgroundColor in                        self.accountTextfield.backgroundColor = backgroundColor        }                let validPasswordSignal = passWordTextfield.reactive.continuousTextValues.map({            text in                        return self.isPassword()        })                validPasswordSignal.map({            isValidPassword in                        return isValidPassword ? UIColor.red : UIColor.yellow        }).observeValues {            backgroundColor in                        self.passWordTextfield.backgroundColor = backgroundColor        }复制代码

同样的,我们使用map函数把Bool映射成UIColor,然后观察Value的值,根据Value事件传来的颜色来改变accountTextfield和passWordTextfield的背景颜色。这样,当账号为110或者密码为110,背景颜色就会高亮成红色,表示正确,输入其他变为黄色,表示错误。

多个信号结合在一起

登录按钮只有在username text field和password text field合法的时候才能被按下去

let signUpActiveSignal = Signal.combineLatest(validUsernameSignal, validPasswordSignal)                signUpActiveSignal.map({            (isValidUsername, isValidPassword) in                        return isValidUsername && isValidPassword        }).observeValues {            signupActive in                        self.loginBtn.isEnabled = signupActive        }        复制代码

上面的代码中我们用Signal(Signal是ReactiveSwift的基本类型,所以我们要import ReactiveSwift)的Signal.combineLatest方法将validUsernameSignal和validPasswordSignal两个信号结合在一起,再将它们映射成一个Bool信号来表明username text field和password text field是否同时合法。

之后,通过观察Value事件,我们将信号传过来的值赋值给loginBtn。这样,loginBtn的可用性就可以通过信号来控制了。

在ReactiveSwift中,你可以做到更酷,把上面代码替换成:

loginBtn.reactive.isEnabled <~ Signal.combineLatest(validUsernameSignal, validPasswordSignal).map { $0 && $1 }复制代码

上面的代码展示了ReactiveCocoa的强大之处:

可分开的(Splitting):信号可用拥有多个订阅者(观察者),来作为后续步骤的信号源。注意到validUsernameSignal和validPasswordSignal是两个用来验证username text field和password text field分开的合法的信号,这两个信号有着不同的目的。 可结合的(Combining):多个信号可以结合在一起来创建一个新的信号。更值得兴奋的是,你可以结合任意类型的信号来创建新的信号。

之前我们是直接给loginBtn添加方法

loginBtn.addTarget(self, action: #selector(loginBtnAction), for: .touchUpInside)复制代码
@objc  func loginBtnAction()  {        print("login");    }复制代码

我们可以直接使用controlEvents

let signInSignal = loginBtn.reactive.controlEvents(.touchUpInside)                signInSignal.observeValues {_ in            print("button clicked")        }  复制代码

转载于:https://juejin.im/post/5a542d1ff265da3e2e625a6a

你可能感兴趣的文章
clone远程代码及push
查看>>
201621123075作业09-集合与泛型
查看>>
区块链简介(摘自区块链开发实战书籍)
查看>>
js导出excel
查看>>
HDU 1796 How many integers can you find 容斥原理
查看>>
highcharts API 中文
查看>>
第一章计算机网络概述
查看>>
perl模块 Compress::Raw::Lzma 的安装
查看>>
关于计算文字显示占用画面大小(System.Drawing.Graphics.MeasureString)
查看>>
可重入函数与不可重入函数
查看>>
[转] 深入剖析 linux GCC 4.4 的 STL string
查看>>
常用Web Service汇总(天气预报、时刻表等)
查看>>
resin app server安装总结
查看>>
抓取新浪新闻列表实例
查看>>
[04-06]鼠标悬停图片时,实现抖动效果
查看>>
抽象类和接口的区别
查看>>
react 自定义 TabBar 组件
查看>>
Palindrome Pairs
查看>>
项目测试随笔
查看>>
poj3261 -- Milk Patterns
查看>>