4

我在另一个 parentVC(vc1) 中的 parentVC(vc2) 中有一个 childVC(vc3)。我这样做是出于动画目的。

发生的事情是我将 vc3 作为孩子添加到 vc2。我有一个推动 vc1 的 collectionView。一旦 vc1 出现在场景中,就会将 vc2 添加到其中。当我将 vc1 从堆栈中弹出并返回到 collectionView 时,vc1 中的 deinit 会被调用,但是 vc2 中的 deinit 永远不会被调用。

vc2 中的 deinit 是否应该被调用,即使它是 vc1 的孩子?或者可能是因为 thirdVC 在 secondVC 内部创建了对自身的强引用?

在其中添加了 ThirdVC 的 SecondVC:

class SecondController: UIViewController {

override func viewDidLoad() {
        super.viewDidLoad()

        let thirdVC = ThirdController()
        addChildViewController(thirdVC)
        view.addSubview(thirdVC.view)
        thirdVC.didMove(toParentViewController: self)
}

 // this never runs when the firstVC is popped off the stack
deinit{
     print("the secondVC has be deallocated")
}
}

集合视图:

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

        let firstVC = FirstController()
        navigationController?.pushViewController(firstVC, animated: true)
    }

第一VC:

class FirstController: UIViewController {

override func viewDidLoad() {
        super.viewDidLoad()

        let secondVC = SecondController()
        addChildViewController(secondVC)
        view.addSubview(secondVC.view)
        secondVC.didMove(toParentViewController: self)
}

// this runs when popped off the stack
deinit{
     print("the firstVC has be deallocated")
}
}
4

2 回答 2

2

我的问题的答案是是的,子视图控制器deinit也应该运行。如果您在子视图控制器中调用 deinit 并且当父级从场景中弹出(或关闭)并且子级的 deinit 没有运行时,那么您就有问题了。

正如@BadhanGanesh 在他问的评论中指出的那样:

您是否在使用任何通知观察者,您在不需要时未能将其删除

@Bruno Pinheiro 在评论中建议:

这似乎是一个强有力的参考问题

他们都是对的。我查看了所有代码,我以为我已经删除了一个 KVO 观察者,但我没有。

长话短说,如果您有一个 View Controller 是另一个 View Controller(父级)的子级,那么一旦父级被释放,那么子级也应该如此。

如果您在父级或子级内部使用任何 KVO 观察者,请确保删除它们,否则您将创建一个强大的保留周期。

于 2018-03-14T19:50:18.950 回答
0

我需要将“弱自我”传递给父视图控制器中的 firebase 观察者以删除保留周期,然后在父控制器和子控制器上调用 deinit:

    func observeFeatureChanged(){
    microbeRef.queryOrdered(byChild: Nodes.TIMESTAMP)
        .observe(.childChanged) { [weak self] (dataSnapshot) in
            if let featureDic = dataSnapshot.value as? [String: Any]{
                let featureName = dataSnapshot.key
                if let index = self?.featureNames.firstIndex(of: featureName){
                    self?.featureNames[index] = featureName
                    self?.featureDictionaries[index] = featureDic
                    let indexpath = IndexPath(item: index, section: 0)
                    self?.tableView.reloadRows(at: [indexpath], with: .automatic)
                }
            }
    }
}
于 2020-04-29T13:06:36.703 回答