【发布时间】:2020-03-29 02:53:32
【问题描述】:
首先是一个简短的介绍,我对 Swift 和一般编程都比较陌生,去年一直在做这件事,并且热爱这个广阔世界的每一个新事物。
我的帖子是关于一些技术建议以及了解我公司正在做出的决定是否有意义。我将首先讨论所建议的设计,然后是我的结论。
正在实施的设计;
我们正在开发一个大型应用程序,这个应用程序有一些流程,它们遵循 5 到 8 个控制器的序列,我们的团队负责人坚持这种设计模式; 让我们称第一个控制器为持有者,持有者(黑色边框)负责拥有一个容器,这个容器有一个适当的导航控制器(红色边框),而且持有者持有那些辅助控制器正在生成的所有数据(橙色) .
此模式试图实现的图表
为此,每个红色边框控制器都有一个方法:
private func getParent() -> HolderViewController? {
if let parent = navigationController?.parent as? HolderViewController {
return parent
}
return nil
}
为了写在持有人中,我们调用方法;
getParent().someModelInstance.someModelProperty = "some data”
结论;
通过导航控制器传递数据似乎违背了单一职责原则。 在每个控制器中创建强引用,即使我确保在流程结束时正确 deinit 导航控制器,这似乎也不是一个好的选择,这可能会导致内存泄漏和保留周期。 由于某种原因,我无法确保两个控制器尝试同时访问相同的属性。 这似乎是单例设计模式,但“范围”有限
决议;
由于我是新人,我在一家公司工作,而且每个公司都有等级制度,所以我的首要目标是了解我的结论是否错误,并对此有更好、更简洁的解释。
首先,为了解决内存泄漏的问题,我创建了一个并发队列。 我没有直接访问模型来写入它,而是尝试通过一种方法来解决它,该方法将使用 keyPath 而不是直接使用模型,这是我用来在模型中写入的方法;
在持有人:
class HolderViewController: UIViewController {
@IBOutlet weak var bottomNavigationContainer: UIView!
private var bottomNavigationController: UINavigationController!
private var someModel: SomeModel!
private let concurrentQueue: DispatchQueue = DispatchQueue(label: "concurrentQueue", attributes: .concurrent)
override func viewDidLoad() {
super.viewDidLoad()
setupBottomNavigation()
}
private func setupBottomNavigation() {
rootController = SecondayViewController()
if let root = rootController {
bottomNavigationController = UINavigationController(rootViewController: root)
addChild(bottomNavigationController)
bottomNavigationController.view.frame = bottomNavigationContainer.bounds
bottomNavigationContainer.addSubview(bottomNavigationController.view)
}
}
}
extension HolderViewController {
public func setValueInModel<Value>(_ value: Value, forKey path: WritableKeyPath<SomeModel, Value>) {
concurrentQueue.async(flags: .barrier) { [weak someModelInstance] in
if var obj = someModelInstance {
obj[keyPath: path] = value
}
}
}
public func readFromHolder() -> SomeModel {
concurrentQueue.sync {
return self.someModelInstance
}
}
}
这个方法会这样调用;
class SecondayViewController: UIViewController {
var someString: String = "some data"
private func getParent() -> HolderViewController? {
if let parent = navigationController?.parent as? HolderViewController {
return parent
}
return nil
}
private func setValueInHolder(string: String) {
getParent().setValueInModel(string, forKey: \.someModelProperty)
}
private func readFromHolder() -> String {
return getParent().readFromHolder().someModelProperty
}
}
这看起来像是一些杂乱的代码来做一件简单的事情,我们可以使用闭包、委托、segues 等……但我的团队领导不喜欢其他更简单和更常见的解决方案。忘了说,我们的每个控制器都有一个 xib,我们不使用故事板。我知道如何使用其他选项的基础知识,我正在尝试了解这是或不是一个好的解决方案,以及为什么,以及我的思维方式和方法是否有意义。
请记住,我得出的每个结论或实施的每个解决方案都可能是错误的,这就是为什么我要与您分享我的想法,以便从您的建议和经验中学习
提前致谢。 :) 保持安全!
【问题讨论】: