在变量的didSet中调用可选函数是不是一种糟糕的做法



我一直在寻找一种在变量更新时自动更新UI的简单方法。常规KVO是如此混乱的代码,所以我一直在研究RxSwift、ReactiveCocoa等,但发现这些很难掌握,还有很多新对象和太多我不需要的东西。

我一直在玩一个变量的didSet,以及我的对象中的emtpy可选函数。希望展示起来比解释起来容易:

自定义对象(视图模型)

class AwesomeViewModel{
var awesomeText:String { didSet { updateBlock?() } }
var updateBlock:(()->())?
init(awesomeText:String){
self.awesomeText = awesomeText
}
}

和自定义UIView:

class AwesomeView:UIView{
@IBOutlet weak var awesomeLabel: UILabel!
func bindViewModel(viewModel:AwesomeViewModel){
viewModel.updateBlock = { [weak self] in
self?.awesomeLabel.text = viewModel.awesomeText
}
viewModel.updateBlock?()
}
}

假设这个自定义视图AwesomeView作为出口存在于UIViewController中。我创建了一个AwesomeViewModel的实例,然后调用self.awesomeView.bindViewModel(awesomeViewModel)

稍后,当我在UIViewController(或其他任何地方,就这一点而言,它可以传递)中执行类似awesomeViewModel.awesomeText = "Hello World"的操作时,viewModel的变量的didSet将触发可选函数updateBlock。由于此功能已由自定义视图AwesomeView设置,因此它将自动更新该视图中标签中的文本。

我觉得这很酷,很容易理解,但这有什么副作用吗,或者我没有看到什么?这是不好的做法吗?它似乎比使用具有所有功能和观察等的标准KVO容易得多。

我想将其用于UITableViewCell的,其中bindViewModel()将在cellForRowAtIndexPath中调用。我不认为有任何保留周期或其他什么,但我不太善于发现它们。。

在将这种方法应用于我的应用程序之前,我希望能了解它的优缺点,但却发现这是世界上最愚蠢的想法。但对我来说似乎还可以。

我认为学习RxSwift是个好主意。然而,与此同时,你所做的大部分都很好。这种方法的局限性在于,您只能进行一次回调;RxSwift将允许任意数量的订阅一个Observable。我提前道歉,这个答案是基于公平的意见。

我会将updateBlock更改为将"观察到的"值作为参数,即

var updateBlock: ((String) -> ())? 

因为这有助于避免保留周期,并可能重命名updateBlock以更准确地反映哪个值发生了变化,即

var awesomeTextUpdate: ((String) -> ())? 

然而,@rmaddy是对的,这将成为一种痛苦,你可能希望观察到多种属性。这可以通过属性及其值的枚举来部分解决,例如

class AwesomeViewModel {
enum Property {
case awesomeText(String)
case awesomeNumber(Int)
}
}

并将CCD_ 15更改为类型

var updateBlock: ((AwesomeViewModel.Property) -> ())?

CCD_ 16到

var awesomeText: String { 
didSet {
updateBlock?(.awesomeText(awesomeText))
}
}

然后客户端可以在Property枚举上简单地switch;在他们不关心的地方中断并访问他们关心的地方。如果你有许多潜在的可观察属性,但客户端在特定情况下只需要一个,这可能会变得很痛苦。

如果看起来没有正确的妥协,那主要是因为没有,RxSwift可能是更好的长期解决方案。然而,如果你不想广泛复制这种范式,那么一个可选的功能就可以了。记住:不要重复自己。

tl;博士,你所做的看起来很合理,但规模不大。

相关内容

  • 没有找到相关文章

最新更新