技术共享|移动开发咋入门?Apple新推RxSwift实战

手机APP/开发
380
0
0
2022-05-15
标签   APP开发
RxSwift 是在 Apple 推出 Swift 后,针对 Swift 语言 ReactiveX 推出 Reactive Extensions 系列一个实现库;除此之外,ReactiveX 还推出了 RxJava,RxAndroid,RxPHP 等蕴含类似思想的框架。

为什么要学习RxSwift

我们知道 C 语言的面向过程,Objective-C、C++ 面向对象编程, Java 的 Spring 框架提出了面向切面编程的思想,学习 RxSwift 不是学习如何使用第三方库,而是学习一种编程思想--函数响应式编程;另外,RxSwift是ReactiveX提出的,其他语言的Rx项目在编程思想上也是一致的,因此如果我们学会了如何使用RxSwift,再去学习Rx.Net, RxJava 或者 RxJS就是小菜一碟,只是语言语法上的差异。这真的就是learn once, apply everywhere.

RxSwift的优点

Composable 可组合,在设计模式中有一种模式叫做组合模式,你可以方便的用不同的组合实现不同的类

Reusable 代码可重用,原因很简单,对应RxSwift,就是一堆Obserable

Declarative 响应式的,因为状态不可变,只有数据变化 Understandable and concise 简洁,容易理解。

Stable 稳定,因为RxSwift写出的代码,单元测试时分方便

Less stateful “无”状态性,因为对于响应式编程,你的应用程序就是一堆数据流

Without leaks 没有泄漏,因为资源管理非常简单

RxSwift实践

1、通过pods引入RxSwift和RxCocoa三方库

RxSwift 是 Swift 语言的函数响应式编程框架。 RxCocoa 则是对苹果原声面向对象 Api 的封装。

pod 'RxSwift'

pod 'RxCocoa'

需要用到 RxSwift 相关内容的类里面,引入模块即可。

import RxSwift

import RxCocoa

2、RxSwift的简单应用

监听UITextField的输入,并把输入的文字展示在UILabel上

(1) 传统做法

成为文本框的代理

textField1.delegate = self

textField2.delegate = self

实现文本框协议

// MARK: - UITextFieldDelegate
extension ViewController: UITextFieldDelegate {
    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        // 判断是哪一个输入框发生改变  
        if textField == textField1 {
            print("输入框1 改变")
        } else {
            print("输入框2 改变")
        }
        return true
    }
}

这样做可能面临的问题:界面有多个文本框,需要每个都实现代理,并且需要判断是哪一个文本框发生了改变,维护成本比较高,代码可读性差。

(2) RxSwift做法

首先订阅 UITextField,文字输入改变时通过闭包回调,进行打印

TF1.rx.text .subscribe { (str: Event<String?>) in

print(str)

}.addDisposableTo(bag)

把UITextField文字改变的Obserable与UILabel文字改变的Obserale进行绑定

TF1.rx.text .bindTo(label.rx.text).addDisposableTo(bag)

(3) 效果图

技术共享|移动开发咋入门?Apple新推RxSwift实战

3、使用RxSwift重写车务通项目中事件提醒列表

tips:在开始之前请确认安装了RxDataSources这个三方库,如果没有这个库,会崩溃至死。

RxDataSources是使用RxSwift对UITableView和UICollectionView的数据源做了一层包装,引入方法与见步骤1

(1) 为UITableView中的每一个Cell的数据基本结构封装数据模型 RXTestSectionModel包含两个参数,headerName为section的名字,items为这个section中所包含的item数组

struct RXTestItemModel {
    let licensePlate: String 
    let eventType: String 
    let eventTime: String 
    let isDeal: String
}
//其实这个可以写成 SectionModel<String, RXTestItemModel> ,但是可读性不好,因此在这个的基础上封装一下sectionModel
struct RXTestSectionModel {
    let headerName: String 
    var items: [Item]
}
extension RXTestSectionModel: SectionModelType {
    typealias Item = RXTestItemModel 
    init(original: RXTestSectionModel, items: [Item]) {
        self = original
        self.items = items
    }
}

(2)在视图控制器中声明dataSource属性

let dataSource = RxTableViewSectionedReloadDataSource<RXTestSectionModel>()
    //(3) 自定义UITableViewCell UI的相关代码在这里略去,在Cell中定义一个item数据模型的变量  
    var innerItemModel: RXTestItemModel?
    var itemModel: RXTestItemModel? {
    set {
        innerItemModel = newValue
        licensePlateLb.text = innerItemModel?.licensePlate
        alarmNameLb.text = innerItemModel?.eventType
        alarmTimeLb.text = innerItemModel?.eventTime
        if innerItemModel?.isDeal == "1" {
            dealStatusImageView.image = UIImage.init(named: "chuli_icon")
        } else {
            dealStatusImageView.image = UIImage.init(named: "weichuli_icon")
        }
    }
    get {
        return innerItemModel
    } 
}

(4) 配置Cell

dataSource.configureCell = {
(_, tableView: UITableView, indexPath: IndexPath, eventItemModel: RXTestItemModel) in
    let cell = tableView.dequeueReusableCell(withIdentifier: RXTestTableViewCell.CellIdentify(), for: indexPath) as! RXTestTableViewCell
    cell.tag = indexPath.row
    cell.itemModel = eventItemModel
    return cell
}

(5) 从接口请求数据并复制给一个[RXTestSectionModel] () 类型的Variable 在这里,itemsList作为一个桥梁,因为普通数据类型无法被当做被观察对象,因此,我们用itemsList.value来接收数据,在把它与tableView的dataSouce进行数据绑定。

//TIP: Variable 中的类型必须是 实例化的数组 要不然在 itemsList.asObservable().bindTo(innertableview.rx.items(dataSource: dataSource)) .addDisposableTo(bag) 绑定中会有错误

var itemsList: Variable = Variable([RXTestSectionModel]())
    dataprovider.cwtRxQueryAlarmListWith(targetLicensePlate: "", targetTypeId: "1", pageNo: 0, pageSize: 10).subscribe(onNext: { sectionModel in
    self.cmcciotStopLoading()
    print(sectionModel)
    self.itemsList.value = [sectionModel]
}, onError: { 
    errorInfo inself.cmcciotStopLoading()
}).addDisposableTo(bag)
itemsList.asObservable().bindTo(innertableview.rx.items(dataSource: dataSource)) .addDisposableTo(bag)

(6)最终效果图

技术共享|移动开发咋入门?Apple新推RxSwift实战

在RxSwift使用和学习的过程中了解到RxSwift语法更加简洁,使用了更少的中间变量和更少的代码,之前8-9句代码RxSwift几乎1句就可以搞定,但是在代码简洁的同时也发现,其代码可读性不高。如果有任何问题,还请各位大神及时指正。