shallowThought shallowThought - 1 month ago 14
Swift Question

Method not found at runtime

I have the following extension in my personal toolbox library:

public extension UIViewController {

public func removeChildViewControllers() {
for child in self.childViewControllers {
child.willMove(toParentViewController: nil)
child.view.removeFromSuperview()
child.removeFromParentViewController()
}
}

public func addChildViewController(_ controller: UIViewController, embedViewIn containerView: UIView) {
controller.willMove(toParentViewController: self)
addChildViewController(controller)
containerView.addSubview(controller.view)
controller.view.addCustomConstraints(CustomConstrains.FullSizeInSuperview)
controller.didMove(toParentViewController: self)
}
}


From my current app, I call as follows:

private func embedViewController(_ controller: UIViewController) {
removeChildViewControllers()
addChildViewController(controller, embedViewIn: containerView)
}


Everything is working as expected.

Now I add one more convenience Method
removeChildViewController
:

public extension UIViewController {

public func removeChildViewControllers() {
for child in self.childViewControllers {
child.willMove(toParentViewController: nil)
child.view.removeFromSuperview()
child.removeFromParentViewController()
}
}

public func addChildViewController(_ controller: UIViewController, embedViewIn containerView: UIView) {
controller.willMove(toParentViewController: self)
addChildViewController(controller)
containerView.addSubview(controller.view)
controller.view.addCustomConstraints(CustomConstrains.FullSizeInSuperview)
controller.didMove(toParentViewController: self)
}

public func removeChildViewController(_ controller: UIViewController) {
controller.willMove(toParentViewController: nil)
controller.view.removeFromSuperview()
controller.removeFromParentViewController()
}
}


From now on, calling the code which has not been modified crashes at runtime EXC_BAD_ACCESS:

removeChildViewControllers()


To sum it up:

Calling
removeChildViewControllers()
crashes on runtime if the (unused) method
removeChildViewController
exists.

Calling
removeChildViewControllers()
does not crash on runtime if the (unused) method
removeChildViewController
is commented.

Also, calling
removeChildViewControllers()
does not crash on runtime if the (unused) method
removeChildViewController
is renamed to
removeChildViewControllerr
.

Answer

I'm going to guess that this is one of those situations where you are banging into a secret namespace conflict. There probably is a removeChildViewController method hidden in the Objective-C Cocoa world, and you have stumbled over it by duplicating its name. Thus, Objective-C Cocoa chokes at runtime, even though the official API has no problem with it and so there is no trouble getting Swift to compile your code. This sort of thing happens all the time, unfortunately.