Skip to content

Instantly share code, notes, and snippets.

@cellularmitosis
Created November 12, 2015 20:54
Show Gist options
  • Save cellularmitosis/8205610a80112eebd96c to your computer and use it in GitHub Desktop.
Save cellularmitosis/8205610a80112eebd96c to your computer and use it in GitHub Desktop.
UIViewController containment bug demo
//
// ViewController.swift
// ContainerTimingBugDemo
//
// Created by Jason Pepas on 11/12/15.
// Copyright © 2015 Jason Pepas. All rights reserved.
//
/*
Instructions:
1. Create a new "Single View Application" Xcode project.
2. Replace the contents of ViewController.swift with this gist.
3. Uncomment the below test cases one-by-one.
*/
import UIKit
extension UIViewController
{
func containChildViewController(childVC:UIViewController, inView containerView:UIView)
{
addChildViewController(childVC)
containerView.addSubview(childVC.view)
childVC.didMoveToParentViewController(self)
containerView.bringSubviewToFront(childVC.view)
childVC.view.translatesAutoresizingMaskIntoConstraints = false
}
func containChildViewController(child:UIViewController)
{
self.containChildViewController(child, inView:view)
}
}
class ViewController: UIViewController
{
override func viewDidAppear(animated: Bool)
{
super.viewDidAppear(animated)
// self.presentViewController(VCTestCase1(), animated: true, completion: nil)
// self.presentViewController(VCTestCase2(), animated: true, completion: nil)
// self.presentViewController(VCTestCase3(), animated: true, completion: nil)
self.presentViewController(VCTestCase4(), animated: true, completion: nil)
// self.presentViewController(VCTestCase5(), animated: true, completion: nil)
// self.presentViewController(VCTestCase6(), animated: true, completion: nil)
}
}
class VerboseVC: UIViewController
{
override func viewDidLoad()
{
debugPrint("\(self.dynamicType): \(__FUNCTION__)")
super.viewDidLoad()
}
override func viewWillAppear(animated: Bool)
{
debugPrint("\(self.dynamicType): \(__FUNCTION__)")
super.viewWillAppear(animated)
}
override func viewDidAppear(animated: Bool)
{
debugPrint("\(self.dynamicType): \(__FUNCTION__)")
super.viewDidAppear(animated)
}
override func viewWillDisappear(animated: Bool)
{
debugPrint("\(self.dynamicType): \(__FUNCTION__)")
super.viewWillDisappear(animated)
}
override func viewDidDisappear(animated: Bool)
{
debugPrint("\(self.dynamicType): \(__FUNCTION__)")
super.viewDidDisappear(animated)
}
}
class ChildVC: VerboseVC {}
class VCTestCase1: VerboseVC
{
override func viewDidLoad()
{
super.viewDidLoad()
// CORRECT: SubViewController will correctly receive viewWillAppear and viewDidAppear
containChildViewController(ChildVC())
}
}
class VCTestCase2: VerboseVC
{
override func viewWillAppear(animated: Bool)
{
// CORRECT: SubViewController will correctly receive viewWillAppear and viewDidAppear
self.containChildViewController(ChildVC())
super.viewWillAppear(animated)
}
}
class VCTestCase3: VerboseVC
{
override func viewWillAppear(animated: Bool)
{
super.viewWillAppear(animated)
// CORRECT: SubViewController will correctly receive viewWillAppear and viewDidAppear
self.containChildViewController(ChildVC())
}
}
class VCTestCase4: VerboseVC
{
override func viewWillAppear(animated: Bool)
{
super.viewWillAppear(animated)
dispatch_async(dispatch_get_main_queue()) { () -> Void in
/*
ERROR: SubViewController receives viewDidLoad, then viewDidAppear. viewWillAppear is not called.
Specifically, you should see this in the console:
"VCTestCase4: viewDidLoad()"
"VCTestCase4: viewWillAppear"
"ChildVC: viewDidLoad()"
"VCTestCase4: viewDidAppear"
"ChildVC: viewDidAppear"
*/
self.containChildViewController(ChildVC())
}
}
}
class VCTestCase5: VerboseVC
{
override func viewDidAppear(animated: Bool)
{
// CORRECT: SubViewController will correctly receive viewWillAppear and viewDidAppear
self.containChildViewController(ChildVC())
super.viewDidAppear(animated)
}
}
class VCTestCase6: VerboseVC
{
override func viewDidAppear(animated: Bool)
{
super.viewDidAppear(animated)
// CORRECT: SubViewController will correctly receive viewWillAppear and viewDidAppear
self.containChildViewController(ChildVC())
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment