title: iOS Swift: Best practices for starting app with an alternative UIViewController
body: <p><strong>TLDR version</strong>: I try to push the user to a specific <code>UIVIewController</code> in an <strong>iOS</strong> App using <strong>Swift</strong> via methods to check for a saved object. If I put the push to the <code>VC</code> in the <code>ViewDidAppear</code>, it takes several seconds to fire. If I put it in <code>viewDidLayoutSubviews</code>, it throws the warning &quot;<code>Unbalanced calls to begin/end appearance transitions for &lt;ProjectShare.LaunchViewController: 0x7f85a2e37520&gt;.&quot;</code></p>
  <p>I want to know the best way to accomplish this functionality so I have a good user experience and pass Apple submission.</p>
  <p><strong>Details</strong>: I am part of a small class group working on a small software project for iOS using Swift, specifically focused on a group experience using the <code>MultipeerConnectivity</code> framework. We check for a UserInfo object persisted on the device upon launch of the app and if one is not found, we push the user to a screen to add a username and image to share with other users.</p>
  <p>The methods for this are relatively straightforward. We check for the encoded object upon launch via the <code>AppDelegate</code>:</p>
  <pre><code>let fileManager = NSFileManager.defaultManager()
  if fileManager.fileExistsAtPath(self.documentsPath!) {
    var userForLoad = UserInfo.loadTheObject()
    self.defaultUser = userForLoad as UserInfo!
  } else {
    self.defaultUser = nil
  }
  </code></pre>
  <p>This works well, all of the persistence and such are working very well. The app then goes to its initial <code>ViewController</code>, here known as the <code>LaunchViewController:</code> this ViewController is the main menu for the app and will 99.9% of the time be the best starting point, and is needed immediately after creating the <code>UserInfo</code> object. If the <code>LaunchViewController</code> finds that the <code>appDelegate.defaultUser</code> object is <strong>nil</strong>, then I want to force the user to the <code>CreateUserViewController</code> to enter a name and capture an image.</p>
  <pre><code>let appDelegate = UIApplication.sharedApplication().delegate as AppDelegate
  let myUserTest = appDelegate.defaultUser as UserInfo!
  if myUserTest == nil {
      let storyboard = UIStoryboard(name: &quot;Main&quot;, bundle: NSBundle.mainBundle())
      let destinationVC = storyboard.instantiateViewControllerWithIdentifier(&quot;CREATEUSER_VC&quot;) as CreateUserViewController!
      let presentingVC = storyboard.instantiateViewControllerWithIdentifier(&quot;LAUNCHVIEW_VC&quot;) as LaunchViewController!
      destinationvVC.delegate = self
      self.presentViewController(destinationvVC, animated: false, completion: { () -&gt; Void in
        println(&quot;Finished presenting CreateUserViewController.&quot;)
      })
  }
  </code></pre>
  <p>This also works in that it presents the proper view controller, but the timing is tricky.</p>
  <p>If I put this method in <code>viewDidLoad</code> or in <code>viewWillAppear</code>, it fails to fire. if I put it in <code>viewDidAppear</code>, it appears after about two seconds, which isn't a smooth user experience. if I put it in <code>viewDidLayoutSubviews</code>, i get the following warning, which I presume is a submission fail case:</p>
  <pre><code>Unbalanced calls to begin/end appearance transitions for &lt;ProjectShare.LaunchViewController: 0x7f85a2e37520&gt;.
  </code></pre>
  <p>I get similar results if I use a <code>performSegueWithIdentifier</code> method.</p>
  <p>I know that it's possible to select the initial viewController programmatically from the AppDelegate in <code>didFinishLaunchingWithOptions</code> (though i am not familiar with how to do it), but that seems like a poor architectural choice for something that happens exactly once in the user's relationship with the software.</p>
  <p>Basically, looking for help making this happen smoothly for the user and in a manner that is not an apple submission fail case.</p>