My app was working perfectly in iOS8. Its flow was:
VC: View Controller, NVC: Navigation View Controller, ER: Embedded root relationship between NVC and VC, PS: Push Segue, PG: Programmatic presentation
NVC1---(ER)->VC1---(PS)->NVC2---(ER)->VC2 and so on.
The problem was that VC1-(PS)->NVC2 segue did not work, there was no freeze. vc1.prepareForSegue() was executed, but VC2 was not presented. I experimented and found that I did not have the UITextView problem mentioned here.
By following the breadcrumbs outlined below, I got it work after hours of trying in the following way (code at the end):
NVC1---(ER)->VC1---(PG)->VC2
Here are the steps:
As mentioned in Segue issue in iOS9, multiple NVCs are out of style (shame on Apple for suddenly ditching what is actually recommended in your online tutorial and making apps break!). So I modified
NVC1---(ER)->VC1--(PS)->VC2 while VC2 was still embedded in NVC2. I got errors
similar to the StackOverflow post on view not in hierarchy. So I started doing the transition programmatically and after tackling present vs. push ViewController issue that results in "tried to push modally on active view controller"
message and then ViewController lifecycle issues that result in "Unbalanced calls to begin/end appearance transactions"
messages, I got the following code working. Based on this experience, I really think Apple should have left a working thing alone in Xcode7/iOS9 update.
//*********** VC1.swift. A translation of working code
class VC1:UIViewController{
private var viewController2:VC2?
private var showVC2: Bool = false
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
if(showVC2) {
showVC2 = false
self.pushVC2()
}
}//viewWillAppear
private var info:String? // info from incoming user action.
@IBAction unwindToVC1FromUserAction(incomingSegue: UIStoryboardSegue?) {
// Do app-specific stuff to get info from incomingSegue and
// store in self.info variables.
let myboard: UIStoryBoard = self.storyboard!;
self.viewController2 = myboard.instantiateViewControllerWithIdentifier(
"VC2 Storyboard ID") as! VC2
self.prepareVC2() // Pass info to VC2.info, stuff you would have done in prepareForSegue
showVC2= true
} //unwind
private func prepareVC2() {
self.viewController2.info = self.info // etc..
}
private func pushVC2() {
self.navigationController!.pushViewController(viewController2!, animated:false)
}
} //class