初学 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. 使用jQuery获取Bootstrap Switch的值

    $('#switcher').bootstrapSwitch('state'); // true || false $('#switcher').bootstrapSwitch('toggleStat ...

  2. C#实现插入排序法

    private int[] test_Insertion(int[] list) //插入排序 传入数组 3, 6, 2, 1, 9, 5, 4, 7 { ;i<list.Length;i++) ...

  3. 关于sharepoint 2010无法显示用户中文名的解决方法和详细剖析

    相信这个问题许多做sharepoint的朋友都曾经遇到过,就是本来很正常的中文用户名莫名其妙的变成了“域名\账号”,我本人也遇到过好多次,每次都是百度谷歌一下草草解决问题,始终也没真正去弄明白是怎么回 ...

  4. asp快速开发方法之分页函数

    log_Content "自己常用的ASP分页代码,将以下代码放入你的函数文件内,在使用的文件内写上<!--#include file="调用文件.asp" /&g ...

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

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

  6. sql 理解视图

    可以看作是定义在sqlserver上的虚拟的表,本身并不存储数据,仅仅存储一个select语句和涉及的表的引用 通过视图,客户端不再需要知道底层表结构和其之间的关系,视图提供了一个统一访问数据的接口 ...

  7. vmware workstation 12 安装windows7 网卡不能安装驱动的问题

    在使用vmware workstation 12 安装windows7 之后,网卡不能安装驱动不能正常显示网络连接,需要修改该虚拟机的".vmx"配置文件 在配置文件中添加下面一行 ...

  8. 第一篇、CSS3_transtion的使用

    <html> <head> <title>这是一个CSS3的特性</title> <style> #box{ width: 150px; h ...

  9. oc 基础知识

    一.枚举 结构体 typedef enum{ sexMan, sexWoman }Sex;   tydedef struct{    int year;    int month;    int da ...

  10. 九度OJ 1447 最短路 1008 最短路径问题

    题目地址:http://ac.jobdu.com/problem.php?pid=1447 题目描述: 在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shirt.但是每当我们的工作人员把上 ...