【问题标题】:Why Does a UIViewController With a Child View Controller Sometimes Return children[0].isEmpty = true?为什么带有子视图控制器的 UIViewController 有时会返回 children[0].isEmpty = true?
【发布时间】:2019-06-06 09:28:42
【问题描述】:

当我尝试使用 self.children[0].currentInfo = updatedInfo 将 updatedInfo 从父 UIViewController 传递到嵌入式/子 UIViewController 时出现此问题。事实证明,在父视图控制器的“普通”函数中,这工作得很好。但是从父视图控制器的委托函数内部,它使程序崩溃了。显然,有时(但并非总是)self.children.isEmpty = true 在委托函数内部。

在不知道原因的情况下,我不知道如何可靠地使用self.children 来传递信息。但我不想只是避免使用它,因为我不理解它。任何见解将不胜感激。

由于我的应用程序引入了太多复杂的因素,我决定通过创建一个非常简单的“玩具”应用程序来研究这个问题。这是我所拥有的(代码在故事板的屏幕截图下方):

在 MainViewController 文件中,有

import UIKit

class MainViewController: UIViewController, InfoDelegate {

    var text = "Text from MainViewController"

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = UIColor.lightGray
        printString("Text from MainViewController's viewDidLoad")
    }

    // Ordinary func
    func printString(_ string: String) {
        print(string)
        print("In printString, self.children.isEmpty is \(self.children.isEmpty)")
    }

    // Delegate func
    func messageString(_ string: String) {
        print(string)
        print("In messageString, self.children.isEmpty is \(self.children.isEmpty)")
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

        if let textViewController = segue.destination as? TextViewController {
            textViewController.text = text
            textViewController.delegate = self
        }
    }
}

在TextViewController中,有

import UIKit

protocol InfoDelegate: AnyObject { func messageString(_ string: String) }

class TextViewController: UIViewController {

    @IBOutlet weak var textView: UITextView!
    var text = "Text from TextViewController"
    weak var delegate: InfoDelegate?

    override func viewDidLoad() {
        super.viewDidLoad()
        textView.text = text
        delegate?.messageString("Text from TextViewController's InfoDelegate")
    }
}

【问题讨论】:

  • children 数组永远不会为空,如果你正确地遵循了 vc 遏制
  • @Sh_Khan,我不知道您所说的“vc 遏制”指的是什么。我没有这样做吗?如果是,怎么做?
  • 它是指以编程方式或通过 IB 中的 containerView 将子代添加到 vc
  • 如截图所示,子vc是IB中的containerView添加的。所以大概我遵循了vc遏制,然后。然而,children 数组是空的。我错过了什么吗?
  • viewDidLoad 中是否为空??

标签: ios swift cocoa-touch uiviewcontroller delegation


【解决方案1】:

viewDidLoadMainViewController

if let child = self.children.first as? TextViewController { 
  child.text = text 
  child.delegate = self
}
else {
  print("problem setting the child ",self.children.count)
}

【讨论】:

  • 添加 textViewController.loadViewIfNeeded() 似乎已经停止了委托函数的执行。插入之前,输出为Text from TextViewController's InfoDelegate In messageString, self.children.isEmpty is true Text from MainViewController's viewDidLoad In printString, self.children.isEmpty is false' Now it's just Text from MainViewController的viewDidLoad printString中,self.children.isEmpty为false`
  • 将该代码添加到viewDidLoadMainViewController 并不能消除问题。委托函数中的打印命令仍然产生In messageString, self.children.isEmpty is true
  • children 数组在childs'viewDidLoad ==> override var children:[UIViewController] { didSet { } } 之后得到它的赋值,并在它被赋值时跟踪
【解决方案2】:

prepare(for:sender:) 方法在目标视图控制器的视图加载之前被调用。它可能在子视图控制器安装到父视图控制器的children 数组之前也被调用。 (我没有对此进行测试,但它是有道理的。在创建目标后立即调用prepare(for:sender:),让您有机会进行早期设置。)

我建议将 didSet 添加到您孩子的 delegate 属性中并对其进行测试。向您的委托协议添加一个测试amIAChildYet 方法,并在子视图控制器的委托属性的didSet() 方法中调用它,以查看设置的顺序。

【讨论】:

  • 抱歉,我不知道如何实施您的建议。根据我的设置,您的第一段表明事情应该正常进行。但是,当然,我们知道他们没有。关于您添加 didSet 的具体建议,我不知道应该在哪里放什么。我还在学习OOP,由于我不是专业的程序员,所以我有时也会忘记我有一段时间没用过的东西。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-21
  • 2014-10-10
  • 2021-03-23
  • 1970-01-01
  • 2017-01-16
相关资源
最近更新 更多