iOS Swift之RxSwift初探

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)

猜你喜欢

转载自blog.csdn.net/wywinstonwy/article/details/126717387