返回顶部
首页 > 资讯 > 移动开发 >RxSwift(一)初窥门径
  • 573
分享到

RxSwift(一)初窥门径

rxswiftswiftios 2023-09-08 22:09:50 573人浏览 安东尼
摘要

前言 这几天学习了一些关于响应式框架的知识,由于 Combine 不支持 iOS13.0以下,所以先学习他的前辈 RxSwift 记录一下。 什么是 RxSwift? RxSwift 是一个 Rx 基

前言

这几天学习了一些关于响应式框架的知识,由于 Combine 不支持 iOS13.0以下,所以先学习他的前辈 RxSwift 记录一下。

什么是 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 三部曲,非常折磨。

RxSwift 能做什么?

首先就帮我们简化原来繁琐的代码。

button点击事件

原先的写法:

 testbutton.addTarget(self, action: pressButton(), for: .touchUpInside) func pressButton() {        print("button click")    }

RxSwift:

 testbutton.rx.tap.subscribe(onNext: {print("button click") })

scrollView 代理

原先的话需要先代理,然后重写方法。
RxSwift:

 scrollView.rx.contentOffset                    .subscribe(onNext: { contentOffset in                        print("contentOffset: \(contentOffset)")                    })

还有通知等方法都可以大大简化。

Demo

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

猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作