带有子视图控制器的UINavigationController的奇怪行为

时间:2018-07-15 16:16:46

标签: ios swift uiviewcontroller uinavigationcontroller uikit

我需要在导航控制器堆栈中所有控制器上的可拖动视图。为了管理该视图和手势识别器,我使用了称为VC的自定义VC。在navController的viewDidLoad方法中,我添加了子控制器。在ChildViewController中,我创建了视图并在didMoveToParent方法中设置了约束。在手势识别器中使用约束常量来计算平移时的视图位置。及其作品。但是每次当我在navController的堆栈中推入或弹出控制器时,navController都会使用约束设置调用ChildViewController的didMoveToParent方法。之后,该手势识别器将无法正常工作。我通过实现isConstrainted变量并在didMoveToParent中添加if语句来解决此问题。现在,约束设置一劳永逸。但是,当我在viewDidLoad中一次添加子vc时,为什么在推入或弹出时navController会调用子vc的didMoveToParent? gitHub https://i.stack.imgur.com/MEeu6.gif上的GIF https://github.com/ayatsev/ChildNavController项目

class CustomNavController: UINavigationController {

    override func viewDidLoad() {
        super.viewDidLoad()
        let childController = ChildViewController()
        addChild(childController)
        view.addSubview(childController.view)
        childController.didMove(toParent: self)
    }

}


class ChildViewController: UIViewController {

var xConstraint: NSLayoutConstraint!
var yConstraint: NSLayoutConstraint!
var isConstrainted = false


lazy var childView: UIView = {
    let cv = UIView()
    cv.translatesAutoresizingMaskIntoConstraints = false
    let panRecognizer = UIPanGestureRecognizer(target: self, action: #selector(handlePan))
    cv.addGestureRecognizer(panRecognizer)
    cv.backgroundColor = .green
    return cv
}()

override func viewDidLoad() {
    super.viewDidLoad()
    view = childView 
}

override func didMove(toParent parent: UIViewController?) {
    print("--- CHILD: Did Move To Parent")
    guard let parent = parent else {return}
    if !isConstrainted {
        childView.widthAnchor.constraint(equalToConstant: 50).isActive = true
        childView.heightAnchor.constraint(equalToConstant: 50).isActive = true
        xConstraint = childView.leadingAnchor.constraint(equalTo: parent.view.leadingAnchor, constant: 40)
        xConstraint.isActive = true
        yConstraint = childView.topAnchor.constraint(equalTo: parent.view.topAnchor, constant: parent.view.frame.height * 2 / 3)
        yConstraint.isActive = true
        isConstrainted = true
    }
}

@objc func handlePan(recognizer: UIPanGestureRecognizer) {
    guard let parent = parent else {return}
    let translation = recognizer.translation(in: parent.view)

    switch recognizer.state {
    case .changed:
        xConstraint.constant += translation.x
        yConstraint.constant += translation.y
        recognizer.setTranslation(CGPoint.zero, in: parent.view)
    default:
        break
    }
}


}

1 个答案:

答案 0 :(得分:0)

  

但是为什么在推入或弹出时navController调用子vc的didMoveToParent

毫无疑问要问“为什么”。这就是系统的工作方式。有时didMove(toParent:)到达时没有相应的willMove(toParent:)。有时didMove(toParent:)到达,即使此视图控制器以前是该父级的子级,而仍是该父级的子级。我知道这似乎很疯狂。但是,您不必理会原因,而应该以对收到的消息做出一致响应的方式进行编码。