RxSwift按钮绑定与Cable枚举优化方案求助
嗨,我来帮你搞定这个优化问题!你的核心需求是把枚举里的大元组方法拆成独立的属性/方法,同时让Rx流能正确调用这些内容对吧?其实关键思路是让合并后的流传递Cable枚举实例本身,而不是直接传递拆解后的元组,这样后续就能灵活调用每个独立的属性或方法了。
第一步:重构Cable枚举
把原来的setProperty()拆成职责单一的计算属性(如果用方法也可以,不过计算属性更符合Swift风格,因为这些是枚举case的固有属性):
enum Cable { case iphone case android case typec // 对应原来的第一个返回值:名称 var title: String { switch self { case .iphone: return "Apple line" case .android: return "Android line" case .typec: return "Type-C line" } } // 对应原来的第二个返回值:类型码 var typeCode: String { switch self { case .iphone: return "1" case .android: return "2" case .typec: return "3" } } // 对应原来的第三个返回值:充电宝图标 var powerBankIcon: UIImage { switch self { case .iphone: return #imageLiteral(resourceName: "icon_borrow_tiv_iphone") case .android: return #imageLiteral(resourceName: "icon_borrow_tiv_android") case .typec: return #imageLiteral(resourceName: "icon_borrow_tiv_typec") } } // 对应原来的第四个返回值:数据线图标 var cableIcon: UIImage { switch self { case .iphone: return #imageLiteral(resourceName: "icon_borrow_t_iphone") case .android: return #imageLiteral(resourceName: "icon_borrow_t_android") case .typec: return #imageLiteral(resourceName: "icon_borrow_t_typec") } } }
这样拆分后,每个属性的用途一目了然,以后要修改某一个值(比如改Android线的名称),直接修改对应的计算属性就行,不用动其他逻辑,维护性强很多。
第二步:修改Rx绑定逻辑
原来的tapStream是直接把枚举的元组值发射出去,现在改成发射Cable枚举实例,后续的map操作就可以直接访问枚举的属性了:
private func bindActions() { // 现在tapStream发射的是Cable枚举实例,语义更明确 let tapStream = Observable.of( appleBtn.rx.tap.map { Cable.iphone }, androidBtn.rx.tap.map { Cable.android }, typeCBtn.rx.tap.map { Cable.typec } ) .merge() // 绑定线名称:直接访问title属性 tapStream.map { localized("label.powerBank") + $0.title } .do(onNext: { [weak self] _ in self?.borrowBtn.isEnabled = true }) .bind(to: lineName) .disposed(by: disposeBag) // 绑定类型码:访问typeCode属性 tapStream.map { $0.typeCode } .bind(to: cableType) .disposed(by: disposeBag) // 绑定充电宝图标:访问powerBankIcon属性 tapStream.map { $0.powerBankIcon } .bind(to: powerBankImage.rx.image) .disposed(by: disposeBag) // 绑定数据线图标:访问cableIcon属性 tapStream.map { $0.cableIcon } .bind(to: cableImage.rx.image) .disposed(by: disposeBag) }
如果一定要用方法而不是计算属性
如果你坚持要写成setTitle()这种方法形式,枚举可以改成这样:
enum Cable { case iphone case android case typec func setTitle() -> String { switch self { case .iphone: return "Apple line" case .android: return "Android line" case .typec: return "Type-C line" } } func setTypeCode() -> String { switch self { case .iphone: return "1" case .android: return "2" case .typec: return "3" } } func setPowerBankIcon() -> UIImage { switch self { case .iphone: return #imageLiteral(resourceName: "icon_borrow_tiv_iphone") case .android: return #imageLiteral(resourceName: "icon_borrow_tiv_android") case .typec: return #imageLiteral(resourceName: "icon_borrow_tiv_typec") } } func setCableIcon() -> UIImage { switch self { case .iphone: return #imageLiteral(resourceName: "icon_borrow_t_iphone") case .android: return #imageLiteral(resourceName: "icon_borrow_t_android") case .typec: return #imageLiteral(resourceName: "icon_borrow_t_typec") } } }
然后绑定的时候只需要把$0.title改成$0.setTitle(),其他类似就行,逻辑是完全一样的。
为什么这样优化更好?
- 语义更清晰:流里传递的是完整的
Cable类型,一眼就能知道这个流代表的是用户选择的数据线类型,而不是一堆无意义的元组值。 - 更安全:原来的元组拆包依赖顺序(比如
name, type, image1, image2),一旦顺序写错就会导致UI显示错误,现在用属性名直接访问,完全不会有这个问题。 - 易维护:以后要新增或修改某个属性,只需要修改枚举对应的部分,不用动Rx绑定的逻辑,耦合度更低。
内容的提问来源于stack exchange,提问作者Yonathan Hans
相关产品推荐
相关产品推荐

