前言 这几天学习了一些关于响应式框架的知识,由于 Combine 不支持 iOS13.0以下,所以先学习他的前辈 RxSwift 记录一下。 什么是 RxSwift? RxSwift 是一个 Rx 基
这几天学习了一些关于响应式框架的知识,由于 Combine 不支持 iOS13.0以下,所以先学习他的前辈 RxSwift 记录一下。
RxSwift 是一个 Rx 基于 Swift 的函数响应式框架,配合 swift 语言的特性,可以写出来更简洁可读性高的代码。
毕竟关键的两个点在于函数和响应式,下面一一来解释一下。
首先对于函数肯定很熟悉了,这里的函数并不是我们想当然认为的函数,而是函数式编程
函数式编程是一种编程范式,我们平常常用的面向对象编程,以及面向对象编程都是命令式编程,怎么解释呢?
命令式编程由一组详细的指令组成,让计算机以一定的顺序执行。之所以被称作“命令式”是因为开发者以非常具体的方式,准确地规定计算机必须做什么。
命令式编程强调描述程序怎么样一步一步地运行。 举个🌰,现在有一个数组,取出其中大于4的元素我们,并且在其中取出是偶数的数,我们正常会使用 for 循环来写。
命令式编程
:
let array = [1,2,3,4,5,6,7,8,9,10] var tempArray = [] for number in array { if (number > 4 && number % 2 == 0) { tempArray.append(number) } }
我们会写一个有顺序的程序,一步一步告诉计算机该怎么做?
下面试试函数式编程
:
let array = [1,2,3,4,5,6,7,8,9,10]var tempArray = array.filter{$0 > 4 && $0 % 2 == 0}
我们告诉了计算机,从数组中过滤出大于4并且是偶数的数。我们无需告诉计算机怎么做?只需要告诉计算机干什么。函数式编程也是声明式编程的子集。
函数式编程
: 在函数式编程中,函数被认为是一等公民,意味着可以将它们赋值给变量,作为参数传入其他函数,或者由函数返回,通过函数的组合解决问题。RxSwift 就为我们提供了很多高阶函数去处理流。
响应式编程有三个核心概念 :数据流,函数式编程,异步观察
数据流:比如说我们常用的 UITextField,假设我们在其中输入文字 “chabuduoxs”,在联想搜索的时候我们会监听输入文字的改变,会接受到 c-ch-cha-chab-chabu-…-chabuduoxs的这样一系列数据,实际上这样的一系列数据就形成了一个数据流,计算机的输入和读取其实都是流。
函数式编程我们提过了,那么异步观察又是什么呢?
实际上就是数据流变化,观察者监听做出对应操作的过程,只不过数据流只关心自己可不可以发送消息,而不管观察者是否能够响应,在 ioS 中我们经常会响应一些事件,比如说 button,tap等。在原生开发中触发对象和响应方法是分离的,尤其是经典的 KVO 三部曲,非常折磨。
首先就帮我们简化原来繁琐的代码。
原先的写法:
testbutton.addTarget(self, action: pressButton(), for: .touchUpInside) func pressButton() { print("button click") }
RxSwift:
testbutton.rx.tap.subscribe(onNext: {print("button click") })
原先的话需要先代理,然后重写方法。
RxSwift:
scrollView.rx.contentOffset .subscribe(onNext: { contentOffset in print("contentOffset: \(contentOffset)") })
还有通知等方法都可以大大简化。
看 api 还是太干了,写个Demo感受一下。
场景如下:首先是一个登录注册页面,当用户输入的用户名合法时,密码才允许输入,当账号和密码都符合要求时,登录按钮就可以被点击,从而完成登录操作。
如果不用 RxSwift 可能是这样写的,先实现 textfield 的代理,重写 textfield 的代理方法,然后在里面做判断 if…然后解锁密码框的可用状态,再监听密码框,这块还得做一下区分,究竟是哪个 textField,然后怎么怎么样,非常繁琐。
如果用RxSwift呢?
func confiGISLogin() { let usernameValid = loginView.nameTextField.rx.text.orEmpty.map{$0 == "Chabuduoxs"}.share(replay: 1) usernameValid.bind(to: loginView.passWordTextField.rx.isEnabled) let passwordValid = loginView.passwordTextField.rx.text.orEmpty.map{$0 == "123456"}.share(replay: 1) let everythingValid = Observable.combineLatest(usernameValid, passwordValid) {$0 && $1}.share(replay: 1) everythingValid.bind(to: loginView.loginButton.rx.isEnabled) loginView.loginButton.rx.tap.subscribe(onNext: { print("登录成功") self.netWorkToGetJSON() }) }
仅仅需要这几行代码就可以实现了这个逻辑了,非常奇妙的体验,完整代码如下,可以感受一下:
//// ViewController.swift// Rx1//// Created by wangbo.almost on 2023/4/7.//import UIKitimport RxCocoaimport RxSwifttypealias jsON = Anyclass ViewController: UIViewController { var button: UIButton = UIButton() var scrollView: UIScrollView = UIScrollView() var loginView: LoginView = LoginView() override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. self.setupLoginView() self.configIsLogin() } func setupLoginView() { loginView.frame = self.view.frame self.view.addSubview(loginView) } func configIsLogin() { let usernameValid = loginView.nameTextField.rx.text.orEmpty.map{$0 == "Chabuduoxs"}.share(replay: 1) usernameValid.bind(to: loginView.passwordTextField.rx.isEnabled) let passwordValid = loginView.passwordTextField.rx.text.orEmpty.map{$0 == "123456"}.share(replay: 1) let everythingValid = Observable.combineLatest(usernameValid, passwordValid) {$0 && $1}.share(replay: 1) everythingValid.bind(to: loginView.loginButton.rx.isEnabled) loginView.loginButton.rx.tap.subscribe(onNext: { print("登录成功") self.netWorkToGetJson() }) } // addtarget func setupButton() { button.setTitle("登录", for: .nORMal) button.backgroundColor = UIColor.orange button.setTitleColor(.black, for: .normal) button.frame = CGRect(x: 100, y: 100, width: 100, height: 30) button.rx.tap.subscribe(onNext: { print("button tapped") }) self.view .addSubview(button) } // delegate func setupUIScrollView() { scrollView.frame = CGRect(x: 0, y: 100, width: 390, height: 1000) scrollView.backgroundColor = UIColor.red scrollView.rx.contentOffset .subscribe(onNext: { contentOffset in print("contentOffset: \(contentOffset)") }) self.view.addSubview(scrollView) } // observable func netWorkToGetJson() { let json: Observable<JSON> = Observable.create { (observer) -> Disposable in let urlString:String = "https://www.baidu.com" let url = URL(string: urlString) let urlRequest = URLRequest(url: url!) let task = URLSession.shared.dataTask(with: urlRequest) {data, _, error in guard error == nil else { observer.onError(error!) return } guard let data = data, let jsonObject = try?JSONSerialization.jsonObject(with: data, options: .mutableLeaves) else { // 处理json异常 return } observer.onNext(jsonObject) observer.onCompleted()} task.resume() return Disposables.create{task.cancel()} } json.subscribe(onNext: { json in print("getJsonSuccess: \(json)") },onError: { error in print("getJsonFailed: \(error)") },onCompleted: { print("getJsonCompleted") }) } func handleArray(_ array:Array<Int>) -> Array<Int>{ var tempArray = array.filter{$0 > 4 && $0 % 2 == 0} return tempArray }}
//// LoginView.swift// Rx1//// Created by wangbo.almost on 2023/4/7.//import UIKitclass LoginView: UIView { var nameLabel: UILabel = UILabel() var passwordLabel: UILabel = UILabel() var nameTextField: UITextField = UITextField() var passwordTextField: UITextField = UITextField() var loginButton: UIButton = UIButton(type: .roundedRect) override init(frame: CGRect) { super.init(frame: frame) self.setupView() } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) self.setupView() } func setupView() { nameLabel.text = "UserName" nameLabel.font = UIFont.systemFont(ofSize: 30) nameLabel.frame = CGRect(x: 20, y: 80, width: 200, height: 30) self.addSubview(nameLabel) passwordLabel.text = "Password" passwordLabel.font = UIFont.systemFont(ofSize: 30) passwordLabel.frame = CGRect(x: 20, y: 210, width: 200, height: 30) self.addSubview(passwordLabel) nameTextField.frame = CGRect(x: 20, y: 120, width: 250, height: 30) nameTextField.backgroundColor = UIColor.white nameTextField.placeholder = "please input your name" self.addSubview(nameTextField) passwordTextField.frame = CGRect(x: 20, y: 250, width: 250, height: 30) passwordTextField.backgroundColor = UIColor.white passwordTextField.placeholder = "please input your password" self.addSubview(passwordTextField) loginButton.frame = CGRect(x: 120, y: 320, width: 150, height: 40) loginButton.setTitle("Login", for: .normal) loginButton.setTitleColor(.blue, for: .normal) loginButton.backgroundColor = UIColor.green self.addSubview(loginButton) }}
这块还有一段网络请求的优化部分,放到下一次具体分析RxSwift时分析,后续会持续完善,本次仅仅体验一下,小小的demo已经可以感受到搭配swift会很简洁。
来源地址:https://blog.csdn.net/chabuduoxs/article/details/130018965
--结束END--
本文标题: RxSwift(一)初窥门径
本文链接: https://lsjlt.com/news/400681.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-01-21
2023-10-28
2023-10-28
2023-10-27
2023-10-27
2023-10-27
2023-10-27
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0