APM应用性能管理

移动开发:初学 iOS-UIViewController 心得

2016-02-24  本文已影响223人  OneAPM

初学 iOS,本文翻译了一些 iOS 官网上的 UIViewController 的知识点,如有不到位或不正确的地方,还请指正:

本文所介绍的内容的目标:

这是一个UIViewController

这是一个UIViewController

我们为什么要使用视图控制器(View Controllers)?

两个原因

  1. 使用它能够做出更高品质的APP
  2. 它们可被继承

视图控制器(基础知识)

设计模式


设计模式

使用系统视图控制器(System View Controllers)

这里写图片描述

系统视图控制器通包括以下5种

设计模式


设计模式 这里写图片描述

Table view controller: 表视图控制器
Detail controller: 详细控制器
SVC:SSL VPN Client

根视图控制器真的可以管理“整个屏幕里显示的内容”么?

根视图
window.rootViewController= RootViewController
根视图2

自定义视图控制器

Appearance callbacks

(void)viewWillAppear:
(void)viewDidAppear:
(void)viewWillDisappear:
(void)viewDidDisappear:

Rotation callbacks

 (void)viewWillRotateToInterfaceOrientation:duration:
 (void)viewWillAnimateRotationToInterfaceOrientation:
 (void)viewDidRotateFromInterfaceOrientation:

也许在iPhone上很少要关心的屏幕旋转问题的,但是大屏幕的iPad上就不同了,很多时候你需要关心横竖屏。rotation callbacks 一般情况下只需要关心三个方法 :
willRotateToInterfaceOrientation:duration:在旋转开始前,此方法会被调用;
willAnimateRotationToInterfaceOrientation:duration: 此方法的调用在旋转动画block的内部,也就是说在此方法中的代码会作为旋转animation block的一部分;
didRotateFromInterfaceOrientation:此方法会在旋转结束时被调用。而作为view controller container 就要肩负起旋转的决策以及旋转的callbacks的传递的责任。

视图控制器(基础知识)

总结

路线图

了解视图控制器容器

视图控制器

两个层次的故事


两个层次的故事

蓝色:视图颜色
蓝色箭头:子视图关系

金色: 视图控制器颜色
灰色箭头:父视图控制器关系

相对于内容的容器

层次关系

容器层次关系原图
容器层次关系翻译

视图控制器容器

层次关系

控制器层次关系原图1 控制器层次关系翻译1 控制器层次关系原图2 控制器层次关系翻译2 控制器层次关系 控制器层次关系分解

视图控制器容器

层次关系


视图控制器容器

API和控制器层次

邮件视图 控制器层次结构 控制器层次结构翻译

API和控制器层次

视图2 控制器层次结构2

Container View Controller
容器视图控制器包含其他视图控制器所拥有的内容。也就是说一个View Controller显示的某部分内容属于另一个View Controller,那么这个View Controller就是一个Container.
iOS 5.0 开始支持Custom Container View Controller,开放了用于构建自定义Container的接口。如果你想创建一个自己的Container,那么有一些概念还得弄清楚。Container的主要职责就是管理一个或多个Child View Controller的展示的生命周期,需要传递显示以及旋转相关的回调。

控制器层次结构3

显示或者旋转的回调的触发的源头来自于window,一个app首先有一个主window,初始化的时候需要给这个主window指定一个rootViewController,window会将显示相关的回调(viewWillAppear:, viewWillDisappear:, viewDidAppear:, or viewDidDisappear: )以及旋转相关的回调(willRotateToInterfaceOrientation:duration: ,willAnimateRotationToInterfaceOrientation:duration:, didRotateFromInterfaceOrientation:)传递给rootViewController。rootViewController需要再将这些callbacks的调用传递给它的Child View Controllers。

视图控制器容器

API和控制器层次

(void)addChildViewController:(UIViewController *)childController; (void)removeFromParentViewController;
@property(nonatomic,readonly) NSArray *childViewControllers;
(void)willMoveToParentViewController:(UIViewController *)parent; (void)didMoveToParentViewController:(UIViewController *)parent;

视图控制器容器

层次关系


视图控制器容器

不一致的层次结构

不一致的层次结构

UIViewControllerHierarchyInconsistencyException
为什么会这么糟糕?

exception

视图控制器容器

层次关系


callbacks
[self addChildViewController:note];
// Transition to note controller with a flip transition which adds
// tne note view to the window hierarchy and removes the recipe view.
[self transitionFromViewController:recipe 
toViewController:note 
duration:.5 
options:UIViewAnimationOptionTransitionFlipFromRight
animations:nil
completion:^(BOOL finished) {
[note didMoveToParentViewController:self];
}];
[self addChildViewController:note];
// Transition to note controller with a flip transition which adds
// tne note view to the window hierarchy and removes the recipe view.
[self transitionFromViewController:recipe 
toViewController:note 
duration:.5 
options:UIViewAnimationOptionTransitionFlipFromRight
animations:nil
completion:^(BOOL finished) {
[note didMoveToParentViewController:self];
}];

视图控制器容器

API和控制器层次

- (void)transitionFromViewController:(UIViewController *) fromVC 
toViewController:(UIViewController *)toVC 
duration:(NSTimeInterval)duration 
options:(UIViewAnimationOptions)options 
animations:(void (^)(void))animations 
completion:(void (^)(BOOL finished))completion;
- (void)viewWillLayoutSubviews
- (void)viewDidLayoutSubviews

连接

流 — —打开和关闭屏幕时获取视图控制器

连接视图控制器

Containers(容器)

containers
- (void)pushViewController: 
animated:
- (void)popViewControllerAnimated:

Presentation and dismissal

presentation
- (void) presentModalViewController: 
animated: 
- (void) dismissModalViewControllerAnimated:

dimissal
- (void)presentViewController: (UIViewController *)vc 
animated: (BOOL)animated
completion: (void (^)(void))completion;
- (void)dismissViewControllerAnimated:(BOOL)animated
completion: (void (^)(void))completion;

presentation2
- (UIViewController *)parentViewController;
- (UIViewController *)presentingViewController;

presentation3 presentation4

视图操作

presentation5

[root.someView addSubview: vc.view]

manipulation1

[rootVC addChildViewController: vc]

manipulation2

视图控制器容器

inception(启动)

inception

inception(启动)仅在iPad上

@protocol UISplitViewControllerDelegate
...
// Returns YES if a view controller should be hidden by 
// the split view controller in a given orientation.
// (This method is only called on the leftmost view controller 
// and only discriminates portrait from landscape.)
- (BOOL)splitViewController: (UISplitViewController*)svc
shouldHideViewController:(UIViewController *)vc 
inOrientation:(UIInterfaceOrientation)orientation; 
@end

设计一个新的应用程序流

为修正一个食谱应用创建一个应用程序流

recipe1 recipe2 recipe3

Container View Controller Demo

视图控制器容器

演示亮点 — — 容器的移动

- (IBAction)flipToNote
{
if(...) {
...
[self addChildViewController:_noteController];
[self transitionFromViewController:_contentController 
toViewController:_noteController duration:.5 
options:UIViewAnimationOptionTransitionFlipFromRight
animations:nil
completion:^(BOOL finished) {
_flipNoteButton.title = @"Hide Note"; 
_flipNoteButton.action = @selector(flipFromNote);
[_noteController didMoveToParentViewController:self];
}];
}
}

- (IBAction)flipFromNote
{
if(_isNoteBeingShown) {
[_noteController willMoveToParentViewController:nil];
[self transitionFromViewController:_noteController
toViewController:_contentController duration:0.5
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:nil
completion:^(BOOL finished) {
_flipNoteButton.title = @"Show Note"; 
_flipNoteButton.action = @selector(flipToNote);
[_noteController removeFromParentViewController];
_isNoteBeingShown = NO;
}];
}
}

recipe4 recipe5

Moving in and out of containers

- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
if(![self isMovingToParentViewController]) {
[[self parentViewController] updateSelectionForListOfContentIdentifiersIfNecessary];
}
}

inception(启动)

- (BOOL)isMovingToParentViewController;  // Used in appearance callbacks
- (BOOL)isMovingFromParentViewController; // Used in disappearance callbacks
- (BOOL)isBeingPresented;
- (BOOL)isBeingDismissed;
- (BOOL)automaticallyForwardAppearanceAndRotationMethodsToChildViewControllers;


- (IBAction)flipToNote
{
if(...) {
...
[self addChildViewController:_noteController];
[_noteController viewWillAppear: YES];
// Some fancy animation that culminates in the view swap
// E.g [[_contentController.view superview] addSubview:_noteController.view];
...
// Finally this is usually called in a completion handler 
// after the animation completes 
[_noteController viewDidAppear: YES];
[_noteController didMoveToParentViewController:self];
}
}

容器视图控制器示例

为修正一个食谱应用创建一个应用程序流
演示亮点 — — 定义演示文稿上下文

- (IBAction)emailContent
{
UIViewController *presenter= _isNoteBeingShown ? _noteController: 
_contentController;
...
mailController.modalPresentationStyle = UIModalPresentationCurrentContext;
if(_contentController && [MFMailComposeViewController canSendMail]) {
...
data = [_contentProvider dataForContentIdentifier:self.contentControllerIdentifier
mimeType:&mimeType];
note = [_contentProvider noteForContentIdentifier:self.contentControllerIdentifier];
...
[presenter presentViewController:mailController 
animated:YES 
completion:^{[mailController release];}];
}
}

recipe6
mc.modalPresentationStyle = UIModalPresentationCurrentContext;
[rb presentViewController:mailController 
animated:YES 
completion:^{...}];

recipe7 recipe8
mc.modalPresentationStyle = UIModalPresentationCurrentContext;
[note presentViewController:mailController 
animated:YES 
completion:^{...}
recipe9
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | 
UIViewAutoresizingFlexibleHeight;
self.definesPresentationContext = YES;
...
}
@property(nonatomic,assign) BOOL definesPresentationContext;
// A controller that defines the presentation context can also
// specify the modal transition style if this property is true.
@property(nonatomic,assign) BOOL providesPresentationContextTransitionStyle;

视图控制器容器

总结

UIPageViewController

导航与视图之间的页面卷曲过渡

curl

UIPageViewController

一个容器视图控制器

Initialization(初始化)

initialization
- initWithTransitionStyle:
navigationOrientation:
options:
UIPageViewController *myPVC = [[UIPageViewController alloc]
initWithTransitionStyle:UIPageViewControllerTransitionStylePageCurl
navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal
options:[NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInteger:UIPageViewControllerSpineLocationMid],
UIPageViewControllerOptionSpineLocationKey]]

初始视图控制器

Initial
- setViewControllers:
direction:
animated:
completion:
[myPVC setViewControllers:[NSArray arrayWithObjects:firstVC, secondVC, nil] 
direction:UIPageViewControllerNavigationDirectionForward 
animated:NO 
completion:nil];

编程导航

[myPVC setViewControllers:[NSArray arrayWithObjects:thirdVC, fourthVC, nil] 
direction:UIPageViewControllerNavigationDirectionForward 
animated: NO
completion:nil] 
 YES
^(BOOL finished) {
NSLog(@"Page curl completed.");
}];
[myPVC setViewControllers:[NSArray arrayWithObjects:thirdVC, fourthVC, nil] 
direction:UIPageViewControllerNavigationDirectionForward 
animated: 
completion:
YES
^(BOOL finished) {
NSLog(@"Page curl completed.");
}];

交互-用户驱动导航

driven

Demo 总结

OneAPM Mobile Insight ,监控网络请求及网络错误,提升用户留存。访问 OneAPM 官方网站感受更多应用性能优化体验,想阅读更多技术文章,请访问 OneAPM 官方技术博客
本文转自 OneAPM 官方博客

上一篇 下一篇

猜你喜欢

热点阅读