为什么带有子视图控制器的UIViewController有时会返回children [0] .isEmpty = true?

时间:2019-01-11 12:45:20

标签: ios swift cocoa-touch uiviewcontroller delegation

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

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

由于我的应用程序引入了太多复杂因素,因此我决定通过创建一个非常简单的“玩具”应用程序来研究该问题。这就是我所拥有的(代码在情节提要的屏幕快照下方):

enter image description here

在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")
    }
}

2 个答案:

答案 0 :(得分:0)

viewDidLoad的{​​{1}}中

MainViewController

答案 1 :(得分:0)

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

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