【发布时间】:2020-07-31 22:45:49
【问题描述】:
如果我对 IOC 的理解正确,这意味着您为驱动功能而配置的任何框架或模块都应该能够在需要时驱动您的代码(参考:Martin Flower IOC Blog)。这意味着控制是框架驱动的。
我正在浏览一个精彩的博客Future and Promises in Combine。一开始的博客说,通过回调或闭包处理异步行为违反了 IOC。我有点不同意这种说法,但只是想澄清一下我的理解。
场景:
我创建了一个TestFramework,它为框架用户处理一些功能。
public class TestFramework {
typealias UpdatedFrameworkData = (FrameworkData?) -> Void
var giveUpdatedValues: (() -> UpdatedFrameworkData)?
init() { }
private func someAction() {
var updatedValuesCallback = giveUpdatedValues?()
updatedValuesCallback = { [weak self] updatedFrameworkData in
// Perform some action
}
}
}
现在我有一个使用这个框架的类
class FrameworkUser {
let framework: TestFramework = TestFramework()
var updatedValuesCallback: TestFramework.UpdatedFrameworkData?
init() {
setupBinding()
}
private func setupBinding() {
updatedValuesCallback = framework.giveUpdatedValues?()
}
private func getUpdatedData(completion: @escaping TestFramework.UpdatedFrameworkData) {
// Return some data
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
self.updatedValuesCallback?(self.getFrameworkData())
}
}
private func getFrameworkData() -> FrameworkData? {
nil
}
}
框架有时可能需要处理更新的数据,而不是一些陈旧的数据。如果您观察我的框架仍然可以通过用户提供的侦听器控制何时获取更新数据的功能。用户通过异步回调向框架提供数据。
那么,在这种情况下,我是不是通过回调实现了 IOC,还是我错过了什么?
编辑:
我在上面的设置绑定代码中犯了一个小错误。用户仍然调用框架来提供更新的值。
我对上面的代码进行了以下修改,以发现通过回调对程序的异步处理确实违反了 IOC 原则。上面的setupBinding() 方法在绑定到框架回调的方式上是不正确的。应该是这样的:
private func setupBinding() {
framework.giveUpdatedValues = {
return getUpdatedData() // This won't work
}
}
为了遵循 IOC 原则,用户应将其代码绑定到框架回调。上面的代码根本行不通,因为你不能简单地从函数中返回一个转义闭包,而这个闭包将在稍后的某个时间轴上执行。
【问题讨论】:
-
我认为第二个链接是说使用回调闭包实现的异步操作(也称为完成处理程序)违反了 IoC,而不是闭包本身。
-
@Sweeper 感谢您指出这一点。用适当的例子编辑了问题
标签: ios swift callback inversion-of-control combine