Почему UIViewController с дочерним контроллером представления иногда возвращает children [0] .isEmpty = true? - PullRequest
0 голосов
/ 11 января 2019

Эта проблема возникла, когда я пытался передать updatedInfo из родительского UIViewController во встроенный / дочерний UIViewController, используя self.children[0].currentInfo = updatedInfo. Как оказалось, внутри «обычной» функции в родительском контроллере представления это работало нормально. Но изнутри функции делегата в родительском контроллере представления это привело к сбою программы. Очевидно, иногда - но не всегда - 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 голосов
/ 11 января 2019

Метод prepare(for:sender:) вызывается до загрузки представлений контроллера представления назначения. Вероятно, он также вызывается перед установкой дочернего контроллера представления в массив children родителя. (Я не проверял это, но это имеет смысл. prepare(for:sender:) вызывается сразу после создания места назначения, чтобы дать вам возможность выполнить раннюю настройку.)

Я предлагаю добавить didSet к свойству delegate вашего ребенка и проверить его. Добавьте тестовый метод amIAChildYet в ваш протокол делегата и вызовите его в методе didSet () свойства делегата контроллера дочернего представления, чтобы увидеть порядок, в котором все настроено.

0 голосов
/ 11 января 2019

В viewDidLoad из MainViewController

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