使用RxSwift所遇到的坑

摘要:当Swift迅速崛起、并渐渐取代oc成功iOS开发的首选语言的时候,Swift的相关框架也是如雨后春笋般冒了出来。RxSwift作为响应式编程的框架。既能完美兼容Swift,又能强健项目架构。很强大。
前段时间,公司也是用RxSwift的架构重构了公司项目。RxSwift虽然语法简洁精炼,可以很大程度上减少代码数量。但其中也存在一些坑,也不知是自己理解不到位还是确实是坑。在此记录下来。避免以后遇到不知所措

  • UITableView的左滑删除

  1. 场景描述:
    tableView的DataSource是用RxSwift双向绑定的,row的点击也是通过RxSwift来监听的。但我设置tableView的代理给ViewController(控制器),并实现左滑删除的代理时。发现该代理不起作用。

有区别的主要代码如下

/// 声明一个可被观察的数组
var arr = Variable<[XYJPersonMsg]>([])

// 绑定数据源
        _ = arr.asObservable().bind(to: tableView.rx.items(cellIdentifier: XYJPersonMsgCell.cellIdentifi, cellType: XYJPersonMsgCell.self)) { row, element, cell in
            cell.model = element
            // 隐藏mj_footer
            self.tableView.mj_footer.isHidden = self.tableView.mj_footer.frame.origin.y <= self.tableView.frame.maxY
            
        }
        
        
        // 设置代理
        tableView.rx.setDelegate(self).disposed(by: disposeBag)
  1. 解决问题:
    将该控制器中的RxSwift实现方式改成常用的设置代理的方式实现

有区别的主要代码如下:

var arr = [XYJPersonMsg]()

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
        return self.arr.count
    }
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{

        let cell: XYJPersonMsgCell = tableView.dequeueReusableCell(withIdentifier: XYJPersonMsgCell.cellIdentifi) as? XYJPersonMsgCell ?? XYJPersonMsgCell.init(style: .default, reuseIdentifier: XYJPersonMsgCell.cellIdentifi)
        cell.model = self.arr[indexPath.row]

        // 隐藏mj_footer
        self.tableView.mj_footer.isHidden = self.tableView.mj_footer.frame.origin.y <= self.tableView.frame.maxY
        return cell
    }
    
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let vc = XYJPersonDetailVC()
        vc.title = "个人消息"
        vc.personModel = self.arr[indexPath.row]
        
        // 更新阅读状态
        self.arr = self.arr.enumerated().map({ (index,model) -> XYJPersonMsg in
            if indexPath.row == index {
                model.read_flag = 2
            }
            return model
        })
        tableView.reloadData()
        self.navigationController?.pushViewController(vc, animated: true)
    }

公共的代理代码

func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
        let deleteAction = UITableViewRowAction.init(style: .default, title: "         ", handler: { (action, indexPath) in
            
            print("删除")
            
            let personModel = self.arr[indexPath.row] as XYJPersonMsg
            self.deleteMsgStatus(parameters: ["id": personModel.id ?? 0,"read_flag": "3"], row: indexPath.row)
        })
        deleteAction.backgroundColor = UIColor.backgroundColor
        let cancleACtion = UITableViewRowAction.init(style: .default, title: "         ", handler: { (action, indexPath) in
            print("取消")
            tableView.reloadData()
        })
        cancleACtion.backgroundColor = UIColor.backgroundColor
        return [deleteAction, cancleACtion]
    }
  • UITextField的循环监听

  1. 场景描述: UITextField一开始不能输入,当UITextField赋值后,可以改变UITextField的内容

主要实现如下:

设置UITextField的enable为false
首先将UITextField的text绑定到VM的textValue上。

当设置UITextField的text的值得时候,再设置textValue的值

// 主要代码代码如下
realNameView.cardField.field.rx.text.orEmpty.asObservable().bind(to: vm.IDCardNumValue).disposed(by: disposeBag)

self.realNameView.cardField.field.rx.text.orEmpty.asObservable().bind(to: self.vm.IDCardNumValue).disposed(by: self.disposeBag)

self.vm.IDCardNumValue.asObservable().subscribe(onNext: { (idno) in
    self.realNameView.cardField.field.text = idno
}).disposed(by: self.disposeBag)
                
self.vm.IDCardNumValue.value = idno

这样会出现当你赋值完后,再输入的时候会出现输一个值,UITestField里面会出现几个相同的值,比如。输入一个a,UITestField里面会出现好多个a

改进:

设置UITextField的enable为false
首先将UITextField的text绑定到VM的textValue上。
监听textValue并设置UITextField的text的值得时候,再设置textValue的值
// 主要代码如下
realNameView.cardField.field.rx.text.orEmpty.asObservable().bind(to: vm.IDCardNumValue).disposed(by: disposeBag)

self.realNameView.cardField.field.rx.text.orEmpty.asObservable().bind(to: self.vm.IDCardNumValue).disposed(by: self.disposeBag)

self.vm.IDCardNumValue.asObservable().take(2).subscribe(onNext: { (idno) in
    self.realNameView.cardField.field.text = idno
}).disposed(by: self.disposeBag)
                
self.vm.IDCardNumValue.value = idno
  • 按钮的多次监听

  1. 场景描述: UI界面的View会刷新(创建->移除->重新创建),在这个过程中,按钮的点击事件会多次绑定到vm上。当绑定了几次之后,再点击按钮的时候,就会连续发出好几个点击事件
// 设置表单数据,以及表单中事件绑定
    func setSubmitForm(loginFields: [XYJMobilSuanhuaLoginField]) {
        self.loginView.logFieldDatas = loginFields
        // 设置手机号码
        loginFields.forEach({ (loginField) in
            if loginField.name == "phoneNo" {
                self.vm.phoneNo.value = loginField.value ?? ""
            }
        })
        
        self.btnTapbind()
        
        self.countdown()
        
        // 确定登录类型后再进行按钮高亮处理
        self.vm.authenBtnBind()
        
        self.formFieldbind()
        
        // 提交按钮高亮绑定(要在 authenBtnBind()后,再设置)
        self.vm.authenBtnEnable?.asObservable().bind(to: self.loginView.submitBtn.rx.enabled).disposed(by: self.vm.disposeBag!)
        self.loginView.submitBtn.rx.tap.bind(to: self.vm.authenBtnTap!).disposed(by: self.vm.disposeBag!)
        self.vm.authenTapResult?.subscribe(onNext: { (formResult) in
            let result = self.detailForm(result: formResult)
            if result.0 {
                self.submitform(parameters: result.1)
            }
        }).disposed(by: self.vm.disposeBag!)
    }

改进:

在按钮创建,按钮点击事件绑定前,先把前一次绑定的资源释放
// 代码如下
// 设置表单数据,以及表单中事件绑定
    func setSubmitForm(loginFields: [XYJMobilSuanhuaLoginField]) {
        self.loginView.logFieldDatas = loginFields
        // 设置手机号码
        loginFields.forEach({ (loginField) in
            if loginField.name == "phoneNo" {
                self.vm.phoneNo.value = loginField.value ?? ""
            }
        })
        
        self.btnTapbind()
        
        self.countdown()
        
        // 确定登录类型后再进行按钮高亮处理
        self.vm.authenBtnBind()
        
        self.formFieldbind()
        // 资源释放变量也重新创建
        self.vm.disposeBag = DisposeBag()
        
        // 提交按钮高亮绑定(要在 authenBtnBind()后,再设置)
        self.vm.authenBtnEnable?.asObservable().bind(to: self.loginView.submitBtn.rx.enabled).disposed(by: self.vm.disposeBag!)
        self.loginView.submitBtn.rx.tap.bind(to: self.vm.authenBtnTap!).disposed(by: self.vm.disposeBag!)
        self.vm.authenTapResult?.subscribe(onNext: { (formResult) in
            let result = self.detailForm(result: formResult)
            if result.0 {
                self.submitform(parameters: result.1)
            }
        }).disposed(by: self.vm.disposeBag!)
    }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,108评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,699评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,812评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,236评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,583评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,739评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,957评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,704评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,447评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,643评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,133评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,486评论 3 256
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,151评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,108评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,889评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,782评论 2 277
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,681评论 2 272

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 11,623评论 4 59
  • 今天和老公吵架了,孩子才33天,婆婆回家第二天,我们的生活就出现在这次大的摩擦,起因是他做鱼汤时顾着看电视把汤炖糊...
    花间疏篱阅读 318评论 1 0
  • 昨晚到黄山已经是半夜一点了,早上起来天空下起雨来 ,看着雨越下越大,几个同学动摇了,去?不去? 看着远到而来的两个...
    九道智慧慧画阅读 303评论 4 1
  • 一 导语 Good evening!大家晚上好 Oxford Reading TreeStage 1,牛津阅读数系...
    快乐流利说英语阅读 1,581评论 0 0
  • 其实也没什么,就是想发一发长文。 连续几天做了些奇奇怪怪的梦,梦里出现了认识的不认识的人,梦里不安无助哭泣。每每发...
    老艺术家Miky阅读 207评论 0 0