7

I upgraded my Swift app to Xcode 7 / Swift 2.0 and now suddenly certain segues in my app no longer work.

I have a segue popping up a "Check In" modal and it works perfectly, but then I have another segue popping up a "Check Out" modal that's near identical and it doesn't launch and the app is frozen.

I re-created the segue from scratch, confirmed that it is identical to the "Check In" one, and it still doesn't work.

I also, instead, tried launching a blank view instead of my Check Out modal and it works fine.

There are no errors, it just freezes, I did confirm that the "prepareForSegue" portion is being called correctly but the "viewDidLoad" portion of my modal is not being invoked.

FYI, I have auto-layout turned off.

William T.
  • 12,831
  • 4
  • 56
  • 53

5 Answers5

8

Does your "Check Out" modal have a UITextView? If it does, then there's a bug in Xcode 7 / iOS9 where you cannot launch a modal (or any root view) that contains a UITextView if you have set a default text value in storyboard.

A work around is to make sure your UITextView in storyboard is either blank or has the default Lorem Ipsem value and instead, set the text programmatically in code on viewDidLoad.

Hopefully this bug will be fixed soon.

Travis M.
  • 10,930
  • 1
  • 56
  • 72
  • 4
    You can leave the UITextView but remove the text and it works. See this: http://stackoverflow.com/questions/32549020/app-frozen-by-uikit-after-upgrading-to-xcode-7/32549072#32549072 – Yaroslav Sep 18 '15 at 19:41
  • Had been struggling to resolve this issue for past 2 weeks. I did not upgrade my other Mac, kept Xcode 6, to keep working on app in swift1.2. Why this bug is still not fixed? – Sahil Oct 17 '15 at 10:29
1

I suspect there is infinite loop somewhere in you "Check Out" controller code. Try pausing app in debugger after presenting controller (when it freezes) and check stacktrace. If it doesn't help, try commenting-out code line-by-line in viewDidLoad and viewWillAppear to find line causing freeze.

glyuck
  • 3,367
  • 18
  • 14
1

I had this problem, try with this

dispatch_async(dispatch_get_main_queue(), { () -> Void in
            let viewController:UIViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("Storyboard Id")
            self.presentViewController(viewController, animated: true, completion: nil)
        })

You just have to give a storyboard id in your view and normally it's working.

HarryMlk
  • 11
  • 1
1

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
Community
  • 1
  • 1
0

I had this, but it was none of the above. My segue call happened to be inside a block. When I moved the call to the main thread I saw that I had a 'NSUnknownKeyException' error in the new View Controller. Being inside the block seemed to prevent the error from registering in Xcode, so the app just appeared to hang without any errors.

Once that was resolved the original code worked fine.

Al.
  • 173
  • 1
  • 11