gpt4 book ai didi

Swift View 和 Controller 共享变量初始化麻烦

转载 作者:行者123 更新时间:2023-11-30 13:50:56 26 4
gpt4 key购买 nike

我正在将一些代码从 Objc 移植到 Swift。并与 Swift 的初始化生命周期作斗争。从简化的角度来看,我试图在这里发挥 4 名球员的作用:

  1. 称为程序的对象。这是我此时的主要顶级模型对象。其余 3 名玩家都想访问他的实例。
  2. 一个 ProgramEditController,绘制在我的主 Main.storyboard 中。他负责实例化一个初始程序,这不能直接作为属性初始值设定项来完成。
  3. 顶级自定义 UIView 子类,称为 ProgramTimelineView。在Main.storyboard中绘制,管理各种专门的 subview 。链接到我的 ViewController 的属性。也具有其 subview 的属性。它想要访问程序,因此它可以进行布局并将其传递给 subview 。
  4. ProgramTimelineView 的一个特定 subview ,称为 ProgramGridView。这些不是在 XCode Canvas 工具中绘制的,而是由包含的 ProgramTimelineView 直接实例化。它想要访问该计划。使用它来执行他的自定义 drawRect

这是我的 Controller 的相关代码:

class ProgramEditController: UIViewController { 
// MARK: - Variables
@IBOutlet var timelineView:ProgramTimelinesView!

var site = Site()

var program:Program!

// MARK: - Initialize

override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
// set up the new program
self.program = self.site.newProgram()
// get it into our top view before it starts drawing
self.timelineView.program = self.program
}

required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder) // Why does Swift make me have a redundant thing here?
}

}

对于 ProgramTimelinesView:

class ProgramTimelinesView: UIView {
// MARK: - Variables
var gridView = ProgramGridView()

var program:Program! {
didSet {
self.gridView.program = self.program
}
}

// MARK: - Initialization

func addGridView() {
self.gridView.alpha = 0.0
self.gridView.opaque = false
self.addSubview(self.gridView)
}

func commonInit() {
self.addGridView()
}

required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.commonInit()
}

override init(frame: CGRect) {
super.init(frame: frame)
self.commonInit()
}

}

最后是ProgramGridView:

class ProgramGridView: TimeAxisView {
// MARK: - Variables
var program:Program!

override func drawRect(rect: CGRect) {
// access self.program in here
}
}

我认为会发生什么:

  1. ProgramEditController.init(nibName...) 将首先触发。
  2. super 调用会导致我的 ProgramTimelineView.init(coder) 触发。
  3. ProgramTimelineView 实例将首先调用 gridView 初始值设定项,将其设置为新的 ProgramGridView View
  4. ProgramTimelineView.init(coder) 的其余部分将运行,这会将 gridView 添加到 View 树中。
  5. 控制将返回到 ProgramEditController.init(nibName) 初始值设定项。 Controller 的 program 属性将被填充。
  6. 绑定(bind)的 timelineView 将设置其 program 属性。
  7. ProgramTimelineView 将依次设置 ​​gridViewprogram 属性。

不过,在步骤 4 和 5 之间似乎发生了 drawRect() 。这会导致 seg 错误,因为 gridView 的程序还没有设置!但为什么此时要发出drawRect()呢?我认为在所有初始化程序都触发之前不会发生这种情况。但显然一些副作用正在发生。避免这种情况的正确模式/习惯用法是什么?我真的不想把所有的 program! 变成 program? 然后把 let/guards 放在每个地方。

最佳答案

事实证明,我最初的前提存在错误的假设(通常是这种情况)。

从界面生成器资源创建时,不会调用

UIViewController.init(nib...)。但是接口(interface)构建器中链接的局部变量(隐式包装)也不会在 init(coder) 点设置/实现。正确的方法需要进行两次调整:

  1. program 变量的设置移至 init(coder) 初始化器:

例如

required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.program = self.site.newProgram()
}
  • 将其转发到 viewDidLoad() 覆盖中的 View 。
  • 例如

    override func viewDidLoad() {
    super.viewDidLoad()
    self.timelineView.program = self.program
    }

    关于Swift View 和 Controller 共享变量初始化麻烦,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34279275/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com