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

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

  • 理解content view controllers 和 container view controllers

  • 知道如何实现自定义view controller containers 以及 何时使用view controller containers

  • 在iOS5操作系统下使用UIPageViewController

  • 分享一些新的API和使用技巧

这是一个UIViewController

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

两个原因

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

视图控制器(基础知识)

设计模式

  • 它们是MVC中的C

  • 它们管理着“整个屏幕里显示的内容”

  • 它们通常和它们的对象模型打包在一起

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

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

  • TWTweetComposeViewController

  • UIImagePickerController

  • EKEventViewController

  • MFMailComposeViewController

  • MPMediaPickerController

设计模式

  • 它们是MVC中的C

  • 它们管理着“整个屏幕里显示的内容”

  • 它们通常和它们的对象模型打包在一起

  • 你的应用程序可以再各个视图控制器之间移动

    (Your application flows between view controllers)

  • 它们管理“整个屏幕里显示的内容”?

  • 它们看起来有很灵活的边界

  • 他们管理这各自独立的“内容单元”

Table view controller: 表视图控制器

Detail controller: 详细控制器

SVC:SSL VPN Client

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

window.rootViewController= RootViewController

自定义视图控制器

  • 子类的UIViewController
  • 视图控制器与视图层关联
  • 重写所选择的API
  • 在应用程序中添加逻辑
  • 配置tango执行应用程序

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的传递的责任。

视图控制器(基础知识)

总结

  • 视图控制器仅仅只是控制器 —— 是MVC中的C

  • 视图控制器管理视图层次结构 —— 而非单一的视图

  • 视图控制器通常是自包含的(可重复使用)

  • 视图控制器连接并支持通用的iOS应用程序流

路线图

了解视图控制器容器

  • 视图控制器和视图层次

  • 视图控制器互相连接的三种方式

  • 设计自定义容器控制器

  • 探讨如何新增和修改API

视图控制器

两个层次的故事

蓝色:视图颜色

蓝色箭头:子视图关系

金色: 视图控制器颜色

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

相对于内容的容器

层次关系



视图控制器容器

层次关系

视图控制器容器

层次关系

  • 你应该知道些什么?

    容器控制器是负责 父/子 关系的

视图控制器容器

API和控制器层次

API和控制器层次

Container View Controller

容器视图控制器包含其他视图控制器所拥有的内容。也就是说一个View Controller显示的某部分内容属于另一个View Controller,那么这个View Controller就是一个Container.

iOS 5.0 开始支持Custom Container View Controller,开放了用于构建自定义Container的接口。如果你想创建一个自己的Container,那么有一些概念还得弄清楚。Container的主要职责就是管理一个或多个Child View Controller的展示的生命周期,需要传递显示以及旋转相关的回调。

  • UITableViewController

    很多应用程序显示表格数据。因此,iOS提供了一个专门用来管理表格数据的内建的UIViewController类的子类。UITableViewController 管理一个表格视图并支持很多标准表格相关的行为,比如选择(selection)管理,行编辑,以及表格配置。这些额外的支持减少了你创建和初始化一个基于表格界面必须编写的代码总量。你还可以子类化UITableViewController来添加其它自定义行为。

  • Recipe Controller

    食谱控制器

显示或者旋转的回调的触发的源头来自于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

为什么会这么糟糕?

视图控制器容器

层次关系

  • 你应该知道些什么?

    容器控制器是负责 父/子 关系的

    有一致和不一致的层次结构

    这时,其实出现了回调

[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];
}];
  • viewWillAppear:

    该视图添加到 windows 的视图层次结构之前调用

    在 [vc.view layoutSubviews](if necessary)之前调用

  • viewDidAppear:

    该视图添加到视图层次结构之后调用

    在 [vc.view layoutSubviews](if necessary)之后调用

  • viewWillDisappear:

    该视图从 windows 的视图层次结构移除之前调用

  • viewDidDisappear:

    该视图从 windows 的视图层次结构移除之后调用

[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

连接

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

连接视图控制器

  • 通过container controllers(容器控制器)

  • 通过presentation(呈现) 和 dismissal (解散)

  • 通过直接视图操作

Containers(容器)

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

Presentation and dismissal

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

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

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

视图操作

[root.someView addSubview: vc.view]

[rootVC addChildViewController: vc]

视图控制器容器

inception(启动)

  • 你会在什么时候考虑创建一个自定义视图控制器容器?

    Aesthetics(考虑到美观)

    自定义应用程序流

    您的应用程序直接处理视图层次结构

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

设计一个新的应用程序流

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

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;
}];
}
}

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];}];
}
}

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

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

- (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;

视图控制器容器

总结

  • 尽可能利用现有的容器

    视图控制器可以管理多个视图

    不是每个视图都需要一个视图控制器

  • 当需要时,创建自定义视图控制器容器

    定义新的应用程序或实现

    而不是直接视图操作(这将创造出具有前瞻性的应用)

  • 该 API 很简单

    但理解你的层次结构

UIPageViewController

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

UIPageViewController

一个容器视图控制器

  • 管理子视图控制器的当前内容

  • 展示一个已准备的应用程序流程

Initialization(初始化)

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

初始视图控制器

- 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.");
}];

交互-用户驱动导航

Demo 总结

  • 接下来我们知道

    初始化页面视图控制器与过渡样式,导航定位和任何选项 (spine location)
    设置初始视图控制器 (和驱动编程导航)
    通过设置数据源允许用户驱动导航
  • 我们从中学到什么:

    通过放置手势识别器自定义手势区
    在旋转和拖拽过程中改变spine location
  • 理解内容和容器视图控制器之间的区别

  • 使用自定义视图控制器容器...

    。。。定义新的应用程序或looks

    。。。代替直接视图操作

  • 尽可能利用现有的容器

    UINavigationController, UITabBarController, UISplitViewController, etc.

    新的容器视图控制器, UIPageViewController

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

本文转自 OneAPM 官方博客

移动开发:初学 iOS-UIViewController 心得的更多相关文章

  1. [Android开发学iOS系列] iOS写UI的几种方式

    [Android开发学iOS系列] iOS写UI的几种方式 作为一个现代化的平台, iOS的发展也经历了好几个时代. 本文讲讲iOS写UI的几种主要方式和各自的特点. iOS写UI的方式 在iOS中写 ...

  2. 【转载国外好文】代工开发一个iOS应用没有那么容易

    导读:这是来自新加坡的 iOS 开发者 Kent Nguyen 发表在1月底的一篇博文.这篇吐槽文在 iOS 开发圈子里流传甚广,从原文150多个评论就可见一斑,现翻译如下. 让我们开门见山吧:做一个 ...

  3. iOS UIViewController 和 nib 相关的3个方法

    iOS UIViewController 的 awakeFromNib 以及 - (id)initWithCoder:(NSCoder *)aDecoder 和 - (instancetype)ini ...

  4. Safari 前端开发调试 iOS 完美解决方案

    转http://www.2cto.com/kf/201403/283404.html afari 前端开发调试 iOS 完美解决方案 2014-03-05      0个评论    来源:Safari ...

  5. 开发一个iOS应用没有那么容易

    导读:这是来自新加坡的 iOS 开发者 Kent Nguyen 发表在1月底的一篇博文.这篇吐槽文在 iOS 开发圈子里流传甚广,从原文150多个评论就可见一斑,现翻译如下. 让我们开门见山吧:做一个 ...

  6. IOS开发笔记 IOS如何访问通讯录

    IOS开发笔记  IOS如何访问通讯录 其实我是反对这类的需求,你说你读我的隐私,我肯定不愿意的. 幸好ios6.0 以后给了个权限控制.当打开app的时候你可以选择拒绝. 实现方法: [plain] ...

  7. web前端开发与iOS终端开发的异同[转]

    * {-webkit-tap-highlight-color: rgba(0,0,0,0);}html {-webkit-text-size-adjust: none;}body {font-fami ...

  8. 用HTML5/CSS3/JS开发Android/IOS应用框架大全

    现在人人都想成为安卓/IOS应用开发工程师.其实,安卓/IOS应用可以用很多种语言来实现.由于我们前端开发工程师,对HTML5/CSS/JavaScript的网络编程已经相当熟悉了.所以,今天大家将会 ...

  9. 玩转iOS开发:iOS中的GCD开发(三)

    上一章, 我们了解到了GCD里的一些队列和任务的知识, 也实践了一下, 同时我们也对主队列的一些小情况了解了一下, 比如上一章讲到的卡线程的问题, 如果没有看的朋友可以去看看玩转iOS开发:iOS中的 ...

  10. [Android开发学iOS系列] 工具篇: Xcode使用和快捷键

    [Android开发学iOS系列] 工具篇: Xcode使用和快捷键 工欲善其事必先利其器. 编辑 Cmd + N: 新建文件 Option + Cmd + N: 新建文件夹 Cmd + / : 注释 ...

随机推荐

  1. CSS经典布局-圣杯布局、双飞翼布局

    圣杯布局的来历是2006年发在a list part上的这篇文章:In Search of the Holy Grail · An A List Apart Article圣杯是西方表达“渴求之物&q ...

  2. Linux下chkconfig命令详解即添加服务以及两种方式启动关闭系统服务

    The command chkconfig is no longer available in Ubuntu.The equivalent command to chkconfig is update ...

  3. Linq DataTable Group By 分组显示人员明细

    实现功能:       多个字段分组源码样例: 原始数据: 分组后的输出结果: 源代码: public static void PrintPersons() { //准备数据 DataTable dt ...

  4. 编译个性化的openwrt固件

    基本流程是:下载openwrt源码(推荐attitude adjustment版本).执行feeds更新.make menuconfig(通过配置feed.conf.default和menuconfi ...

  5. Ajax的概述与实现过程

    一.ajax概述 1.Ajax是Asynchronous([ə'sɪŋkrənəs) JavaScript XML的简写,不是一门新技术,而是对现有技术的综合利用.这一技术能够向服务器请求额外数据而无 ...

  6. 学习C++ Primer 的个人理解(十一)

    关联容器 就像是个字典, 其元素是 键 - 值 对. 关键字起到索引作用. 有序: map:关联数组:保存 健-值 对 set : 关键字既是值. multimap : 关键字可重复出现的map mu ...

  7. sgu 102 Coprimes

    太水了, 我都不忍心发题解, 但毕竟是sgu上一道题, 我试试能不能一直这么写下去,就是求phi,上代码 #include <cstdio> #include <cstring> ...

  8. RabbitMQ远程访问配置

    1 首先创建一个新的账户 并给上Administrator标签 2然后给这个新账户添加虚拟主机访问权限 3在windows 下的 rabbitmq安装文件下的etc文件下的配置文件添加以下 [    ...

  9. Yii 获取验证码与Yii常用的URL

    $this->createAction('captcha')->getVerifyCode(); //获取当前验证码的值 当前页面url  echo Yii::app()->requ ...

  10. Unity帮助文档打开速度慢解决方法

    使用批量文本替换工具替换掉Unity安装目录中\Editor\Data\Documentation\en\Manual\下的所有文件中的如下两个部分:   1. <script type=&qu ...