Contenu connexe Similaire à Creating Container View Controllers (20) Creating Container View Controllers2. About...
Bob McCune
‣ MN Developer and Instructor
‣ Owner of TapHarmonic, LLC.
‣ Founded Minnesota CocoaHeads in 2008
3. Agenda
What will I learn?
‣ View Controller Overview
‣ Custom Containers Before iOS 5
‣ iOS 5’s View Controller Containment API
‣ Custom Container Demo
5. What is a View Controller?
View Controller Overview
‣ Focal point of most iOS app development
‣ Key Responsibilities:
‣ Defines the application workflow
‣ Manages a view hierarchy
‣ Programmatically
‣ NIB and/or Storyboard
‣ Plays the MVC “Controller” role...
8. MVC Benefits
Core iOS Design Pattern
‣ Clean separation of concerns
‣ Simplifies development
‣ Provides for greater reusability
‣ Improves quality
‣ Allows us to standardize the behavior and
responsibilities at each tier
9. UIViewController Lifecycle
Standardized Behavior
‣ Loading Callbacks
- (void)viewDidLoad;
- (void)viewDidUnload;
‣ Appearance Callbacks
- (void)viewWillAppear:
- (void)viewDidAppear:
- (void)viewWillDisappear:
- (void)viewDidDisappear:
‣ Rotation Callbacks
- (void)willRotateToInterfaceOrientation:
- (void)willAnimateRotationToInterfaceOrientation:
- (void)didRotateFromInterfaceOrientation:
10. View Controller Types
Container vs Content
Container Controllers
‣ Manages a hierarchy of child view controllers
UITabBarController
UINavigationController
UISplitViewController
Content Controllers
‣ Manage the individual screens within an app
‣ Can be used in multiple presentation contexts
‣ Manages a “screenful of content”
14. Why Create Custom Containers?
One Screen, Multiple Controllers
‣ Aesthetics
‣ Create a custom application flow
15. Pre - iOS 5
Custom Containers
The heartbreaking true story
20. What’s the problem?
Custom Container Fail
‣ Appearance Callbacks
- (void)viewWillAppear:
- (void)viewDidAppear:
- (void)viewWillDisappear:
- (void)viewDidDisappear:
‣ Rotation Callbacks
- (void)willRotateToInterfaceOrientation:
- (void)willAnimateRotationToInterfaceOrientation:
- (void)didRotateFromInterfaceOrientation:
‣ Broken View Controller Hierarchy
21. How do you fix it?
Ugly Options
Create a MonstrosityController
Not practical
Create non-UIViewController controllers
Not scalable
Create container and forward callbacks
Incomplete and ugly
24. Object Hierarchies
View vs View Controller
View Controller Hierarchy
UITabBarController
UINavigationController
ContentViewController
25. View Controller Containment
Simple, but subtle
Adding and removing child controllers
- (void)addChildViewController:(UIViewController *)controller;
- (void)removeFromParentViewController;
Accessing the children
@property(nonatomic,readonly) NSArray *children;
Child View Controller Callbacks
- (void)willMoveToParentViewController:(UIViewController *)parent;
- (void)didMoveToParentViewController:(UIViewController *)parent;
26. Containment API Usage
Adding a Child View Controller
[self addChildViewController:controller];
[self.view addSubview:controller.view];
[controller didMoveToParentViewController:self];
view
ParentViewController
willMove
view
ChildViewController
27. Containment API Usage
Adding a Child View Controller
[self addChildViewController:controller];
[self.view addSubview:controller.view];
[controller didMoveToParentViewController:self];
view
ParentViewController
view
ChildViewController
28. Containment API Usage
Adding a Child View Controller
[self addChildViewController:controller];
[self.view addSubview:controller.view];
[controller didMoveToParentViewController:self];
view
ParentViewController
didMove
view
ChildViewController
29. Containment API Usage
Removing a Child View Controller
[controller willMoveToParentViewController:nil];
[controller.view removeFromSuperview];
[controller removeFromParentViewController];
view
ParentViewController
willMove
view
ChildViewController
30. Containment API Usage
Removing a Child View Controller
[controller willMoveToParentViewController:nil];
[controller.view removeFromSuperview];
[controller removeFromParentViewController];
view
ParentViewController
view
ChildViewController
31. Containment API Usage
Removing a Child View Controller
[controller willMoveToParentViewController:nil];
[controller.view removeFromSuperview];
[controller removeFromParentViewController];
view
ParentViewController
didMove
view
ChildViewController
32. View Controller Transitions
Simplifying Transitions
- (void)transitionFromViewController:(UIViewController *)fromVC
toViewController:(UIViewController *)toVC
duration:(NSTimeInterval)duration
options:(UIViewAnimationOptions)options
animations:(void (^)(void))animations
completion:(void (^)(BOOL finished))block;
‣ Convenience method for view controller transitions
‣ Optional, but simplifies and normalizes transitioning
33. Cloning UINavigationController
pushViewController:animated:
- (void)pushViewController:(UIViewController *)toViewController animated:(BOOL)animated {
UIViewController *fromViewController = [self.stack topObject];
toViewController.view.frame = CGRectMake(width, 0.f, width, height);
[self addChildViewController:toViewController];
NSTimeInterval duration = animated ? 0.3f : 0.f;
[self transitionFromViewController:fromViewController
toViewController:toViewController
duration:duration
options:UIViewAnimationCurveEaseInOut
animations:^{
CGRect frame = CGRectMake(-width, 0.f, width, height);
fromViewController.view.frame = frame;
}
completion:^(BOOL complete) {
[toViewController didMoveToParentViewController:self];
[self.stack pushObject:toViewController];
}];
}
34. Cloning UINavigationController
popViewControllerAnimated:
- (UIViewController *)popViewControllerAnimated:(BOOL)animated {
UIViewController *fromViewController = [self.stack popObject];
UIViewController *toViewController = [self.stack topObject];
[fromViewController willMoveToParentViewController:nil];
NSTimeInterval duration = animated ? 0.3f : 0.0f;
[self transitionFromViewController:fromViewController
toViewController:toViewController
duration:duration
options:UIViewAnimationOptionCurveEaseInOut
animations:^{
CGRect frame = CGRectMake(width, 0.f, width, height);
fromViewController.view.frame = frame;
}
completion:^(BOOL complete) {
[fromViewController removeFromParentViewController];
}];
return fromViewController;
}
35. Disabling Auto Forwarding
Fine Tuning Containment
- (BOOL)automaticallyForwardAppearanceAndRotationMethodsToChildViewControllers
{
return NO;
}
• Control timing of appearance and rotation callbacks
• Useful override in complex containment scenarios
38. Outside Callers
Drive-by Adoption
ModalViewController
RootViewController
ChildViewController
- (IBAction)showModalView:(id)sender {
ModalViewController *modalController = [ModalViewController controller];
[self presentViewController:modalController animated:YES completion:nil];
ChildViewController *childController = [ChildViewController controller];
[modalController addChildViewController:childController];
[modalController addSubview:childController.view];
}
39. Disobedient Children
Parents make the rules
CustomContainerController
OtherViewController
ChildViewController
CustomContainerController
- (void)showChildViewController:(UIViewController *)controller {
[self addChildViewController:controller];
controller.view.frame = CGRectMake(0, 0, 320, 480);
[controller didMoveToParentViewController:self];
} [self.view addSubview:controller.view];
ChildViewController
- (void)didMoveToParentViewController:(UIViewController *)parent {
self.view.frame = CGRectMake(0, 260, 320, 220);
[parent.view addSubview:self.view];
}
40. Disobedient Children
Parents make the rules
CustomContainerController
OtherViewController
ChildViewController
CustomContainerController
- (void)showChildViewController:(UIViewController *)controller {
[self addChildViewController:controller];
controller.view.frame = CGRectMake(0, 0, 320, 480);
[controller didMoveToParentViewController:self];
} [self.view addSubview:controller.view];
ChildViewController
- (void)didMoveToParentViewController:(UIViewController *)parent {
self.view.frame = CGRectMake(0, 260, 320, 220);
[parent.view addSubview:self.view];
}
41. Disobedient Children
Parents make the rules
CustomContainerController
OtherViewController
ChildViewController
CustomContainerController
- (void)showChildViewController:(UIViewController *)controller {
[self addChildViewController:controller];
controller.view.frame = CGRectMake(0, 260, 320, 220);
[self.view addSubview:controller.view];
[controller didMoveToParentViewController:self];
}
43. Meddling Parents
Let children be children
ParentViewController
ChildViewController
ParentViewController
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)orientation
duration:(NSTimeInterval)duration {
self.childViewController.button1.frame = // button 1 frame for orientation;
self.childViewController.button2.frame = // button 2 frame for orientation;
self.childViewController.button3.frame = // button 3 frame for orientation;
}
44. Meddling Parents
Let children be children
ParentViewController
ChildViewController
ChildViewController
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)orientation
duration:(NSTimeInterval)duration {
self.button1.frame = // button 1 frame for orientation;
self.button2.frame = // button 2 frame for orientation;
self.button3.frame = // button 3 frame for orientation;
}
46. Summary
View Controller Containment FTW!
‣ Simple, but subtle API. Easy to make mistakes.
‣ Need to understand UIViewController internals
‣ Small, but important, enhancements in iOS 6