iOS Swift之RxSwift初探

2023-11-09  本文已影响0人  Andy_FML

RxSwift: ReactiveX for Swift

那么为什么要使用 RxSwift ?

复合 - Rx 就是复合的代名词

复用 - 因为它易复合

清晰 - 因为声明都是不可变更的

易用 - 因为它抽象了异步编程,使我们统一了代码风格

稳定 - 因为 Rx 是完全通过单元测试的

RxSwift的引入

Podfile文件target中添加一下代码并pod update 、、或者手动下载拖出代码模块

  pod 'RxSwift', '6.5.0'

  pod 'RxCocoa', '6.5.0'

RxSwift的基础应用与传统应用对比

1、Target Action

正常写法

button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)

@objc func buttonTapped() {

    print("button Tapped")

}

RxSwift写法

        button.rx.tap.subscribe{ event in

            print("按钮点击执行")

        }.disposed(by: bag)

//或者

button.rx.tap.subscribe(onNext: {

            print("按钮点击执行111")

        }).disposed(by: bag)

通过Rx使得代码逻辑清晰可见。

2、代理

传统实现方法:

class RxBaseController:UIViewController,UITextFieldDelegate{

        ...

        textfield.delegate = self

    //textfield代理监控

    func textFieldDidChangeSelection(_ textField: UITextField) {

        print("文字变化:\(textField.text!)")

    }

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

        if textField.text!.count > 4 {

            return false

        }

        return true

    }

}

使用Rx实现

textfield.rx.text.subscribe{event in

            print("输入值变化:(event.element)")

        }.disposed(by: bag)

        // 或者

        textfield.rx.text.subscribe (onNext: {string in

          print("输入变化:\(string!)")

        }).disposed(by: bag)

        //将当前文本内容绑定到label上

        textfield.rx.text.bind(to: lb.rx.text).disposed(by: bag)

3、闭包回调

传统实现方式

let url = URL.init(string: "https://www.qctt.cn/home")

        URLSession.shared.dataTask(with: URLRequest.init(url: url!)) { data, response, error in

            guard error == nil else{

                print("Data Task Error: \(error!)")

                return

            }

            guard let data = data else{

                print("Data Task Error: unknown")

                return

            }

            print("Data Task Success with count: \(data.count)")

        }.resume()

Rx实现方式

        //Rx实现方式

        URLSession.shared.rx

            .response(request: URLRequest.init(url: url!))

            .subscribe{ response,data in

            print(data,response)

        } onError: { Error in

            print(Error)

        }

        .disposed(by: bag)

回调也变得十分简单,错误和返回结果分离,逻辑更加清晰。

4、通知

传统实现方式

override func viewDidLoad() {

        self.view.backgroundColor = UIColor.white

        NotificationCenter.default.addObserver(forName:.NSExtensionHostWillEnterForeground, object: nil, queue: nil){ (notification) in

            print("Application Will Enter Foreground")

        }

    }

    deinit {

        NotificationCenter.default.removeObserver(self)

    }

Rx实现方式

NotificationCenter.default.rx.notification(.NSExtensionHostWillEnterForeground)

            .subscribe(onNext: { (notification) in

                print("Application Will Enter Foreground")

            }).disposed(by: bag)

你不需要去管理观察者的生命周期,这样你就有更多精力去关注业务逻辑。

5、多个任务之间有依赖关系

例如,先通过用户名密码取得 Token 然后通过 Token 取得用户信息,

传统实现方法:

class UserInfo{

    var name = ""

    var age = 0

    var sex = 0

}

enum API {

    //通过用户名密码获得一个接口

    static func token(username:String,password:String,

                      sucess:(String)->Void,

                      failure:(Error)->Void){

        print("获取token")

    }

    //通过token获取用户信息

    static func userinfo(token:String,suecess:(UserInfo)->Void,

                        failure:(Error)->Void){

        print("获取用户信息")

    }

调用方式

API.token(username: "wy", password: "pass", sucess: {token in

            API.userinfo(token: token, suecess: {userinfo in

                print(userinfo)

            }, failure: { error in

                print("获取用户信息失败: \(error)")

            })

        }, failure: { error in

            print("获取用户信息失败: \(error)")

        })

通过 Rx 来实现:

    封装接口

/// 通过用户名密码取得一个 token

    static func token(username:String,password:String)->Observable<String>{

    }

    /// 通过 token 取得用户信息

    static func userInfo(token:String)->Observable<UserInfo>{}

调用

/// 通过用户名和密码获取用户信息

        APIRx.token(username: "ddd", password: "ppp")

            .flatMapLatest(APIRx.userInfo).subscribe(onNext: {userInfo in

                print("获取用户信息成功: \(userInfo)")

            }, onError: {error in

                print("获取用户信息失败: \(error)")

            }, onCompleted: {

            }).disposed(by: DisposeBag.init())

这样处理代码更加简洁。

6、等待多个并发任务完成后处理结果

例如,需要将两个网络请求合并成一个,

/// 用 Rx 封装接口

enum API {

    /// 取得老师的详细信息

    static func teacher(teacherId: Int) -> Observable<Teacher> { ... }

    /// 取得老师的评论

    static func teacherComments(teacherId: Int) -> Observable<[Comment]> { ... }

}

/// 同时取得老师信息和老师评论

Observable.zip(

      API.teacher(teacherId: teacherId),

      API.teacherComments(teacherId: teacherId)

    ).subscribe(onNext: { (teacher, comments) in

        print("获取老师信息成功: \(teacher)")

        print("获取老师评论成功: \(comments.count) 条")

    }, onError: { error in

        print("获取老师信息或评论失败: \(error)")

    })

    .disposed(by: disposeBag)

上一篇 下一篇

猜你喜欢

热点阅读