ViewController编程指南展示和过渡-呈现视图控制器

有两种方法在屏幕上显示视图控制器:将其嵌入到容器视图控制器中或呈现它。 容器视图控制器提供应用程序的主导航,但是呈现视图控制器也是一个重要的导航工具。 您使用直接演示在当前视图控制器的顶部显示新的视图控制器。 通常,当您想要实现模态界面时,您可以使用呈现视图控制器,但是您也可以将它们用于其他用途。

支持呈现视图控制器内置在UIViewController类中,并且可用于所有视图控制器对象。 您可以呈现来自任何其他视图控制器的任何视图控制器,虽然UIKit可能会将请求重新路由到不同的视图控制器。 呈现视图控制器创建被称为呈现视图控制器的原始视图控制器和被显示的新视图控制器之间的关系,被称为呈现的视图控制器。 此关系形成视图控制器层次结构的一部分,并且保持就位,直到呈现的视图控制器被解除。

展示与过渡过程

呈现视图控制器是一种快速和简单的方式来将新内容设置到屏幕上。 UIKit中内置的演示机制允许您使用内置或自定义动画显示新的视图控制器。 内置的展示和动画需要很少的代码,因为UIKit处理所有的工作。 您也可以创建自定义展示和动画,而不需要额外的工作,并与任何视图控制器使用它们。

您可以以编程方式或使用segues启动视图控制器的呈现。 如果你在设计时知道你的应用程序的导航,segues是最简单的方式来启动界面。 对于更多动态界面,或在没有专门控制来启动segue的情况下,使用UIViewController的方法来呈现视图控制器。

呈现方式

视图控制器的呈现方式控制其在屏幕上的外观。 UIKit定义了许多标准的呈现方式,每个都有一个特定的外观和意图。 您还可以定义自己的自定义呈现方式。 在设计应用程序时,选择最适合您想要做的操作的呈现方式,并将适当的时候分配给要呈现的视图控制器的modalPresentationStyle属性。

全屏呈现方式

全屏呈现方式覆盖整个屏幕,防止与底层内容的交互。 在水平常规环境中,只有一个全屏方式完全覆盖基础内容。 其余包含调光视图或透明度,以允许下层视图控制器的部分显示。 在水平紧凑的环境中,全屏演示自动适应UIModalPresentationFullScreen方式并涵盖所有底层内容。

图8-1说明使用uimodalpresentationfullscreen,uimodalpresentationpagesheet呈现方式的外观,并在水平正常的环境uimodalpresentationformsheet风格。在图中,顶部左侧的绿色视图控制器呈现顶部右侧的蓝色视图控制器,每个显示样式的结果如下所示。对于一些呈现方式,UIKit插入一个调光的视图的两个视图控制器的内容。

图8-1全屏呈现方式

VCPG_PresentationStyles _fig_8-1_2x.png

注意

当使用UIModalPresentationFullScreen方式呈现视图控制器时,UIKit通常在
转换动画完成后删除基础视图控制器的视图。 您可以通过指定
UIModalPresentationOverFullScreen样式来防止删除这些视图。 当呈现的视
图控制器具有允许基础内容显示的透明区域时,您可以使用该样式。

当使用全屏呈现方式之一时,发起呈现的视图控制器必须自己覆盖整个屏幕。 如果呈现视图控制器不覆盖屏幕,UIKit会在视图控制器层次结构上查找覆盖全屏的,直到它找到一个。 如果它找不到填充屏幕的中间视图控制器,UIKit使用窗口的根视图控制器。

弹出方式

UIModalPresentationPopover方式在弹出视图中显示视图控制器。 弹出式窗口可用于显示附加信息或与关注或选定对象相关的项目列表。 在水平常规环境中,弹出视图仅覆盖屏幕的一部分,如图8-2所示。 在水平紧凑的环境中,默认情况下,popovers适应UIModalPresentationOverFullScreen表示方式。 在popover视图之外轻击会自动关闭popover。

图8-2 弹出呈现方式

VCPG_popover-style_2x.png

因为弹出方式适合在水平紧凑的环境中的全屏显示,所以通常需要修改弹出方式代码来处理适配。 在全屏模式下,您需要一种方法来关闭所显示的popover。 你可以通过添加一个按钮,将popover嵌入一个可忽略的容器视图控制器,或者改变自适应行为本身。

当前上下文方式

UIModalPresentationCurrentContext样式涵盖了接口中的特定视图控制器。 当使用上下文方式时,通过将其definitionsPresentationContext属性设置为YES来指定要覆盖哪个视图控制器。 图8-3示出了仅覆盖拆分视图控制器的一个子视图控制器的当前上下文表示。

图8-3 当前上下文呈现方式

VCPG_CurrentContextStyles_2x.png

注意

当使用UIModalPresentationFullScreen方式呈现视图控制器时,UIKit通常在
转换动画完成后删除基础视图控制器的视图。 您可以通过指定
UIModalPresentationOverCurrentContext样式来防止删除这些视图。 当呈现
的视图控制器具有允许基础内容显示的透明区域时,您可以使用该方式。

定义呈现上下文的视图控制器还可以定义在呈现期间使用的转换动画。 通常,UIKit使用呈现的视图控制器的modalTransitionStyle属性中的值在屏幕上动画显示控制器。 如果演示文稿上下文视图控制器的providesPresentationContextTransitionStyle设置为YES,UIKit将使用该视图控制器的modalTransitionStyle属性中的值。

当转换到水平紧凑环境时,当前上下文样式适应UIModalPresentationFullScreen样式。 要更改此行为,请使用自适应呈现委派来指定不同的呈现样式或视图控制器。

自定义呈现方式

UIModalPresentationCustom方式允许你使用定义的自定义方式来呈现视图控制器。 创建自定义方式涉及对UIPresentationController子类化,并使用其方法将任何自定义视图动画化到屏幕上,并设置呈现的视图控制器的大小和位置。 呈现控制器还处理由于呈现的视图控制器的特性的改变而发生的任何适配。

过渡方式

过渡方式确定用于显示所呈现的视图控制器的动画类型。 对于内置的转换方式,可以将一个标准转换方式分配给要显示的视图控制器的modalTransitionStyle属性。 当您呈现视图控制器时,UIKit将创建与该样式对应的动画。 例如,图8-4说明了标准上滑过渡(UIModalTransitionStyleCoverVertical)如何在屏幕上动画视图控制器。 视图控制器B从屏幕开始并且向上和向上移动视图控制器A的顶部。当视图控制器B被关闭时,动画反转,使得B向下滑动以显示A.

图8-4视图控制器的过渡动画

VCPG_SlideTransition_fig_8-1_2x.png

您可以使用animator对象和转换委托创建自定义转场。 动画制作器对象创建用于将视图控制器放置在屏幕上的过渡动画。 转换委托在适当的时间将动画对象提供给UIKit。

呈现或显示视图控制器

UIViewController类提供了两种显示视图控制器的方法:

  • showViewController:sender:和showDetailViewController:sender:方法提供了最适应和灵活的方式来显示视图控制器。 这些方法让呈现视图控制器决定如何最好地处理呈现。 例如,容器视图控制器可以将视图控制器合并为子控制器,而不是模态地呈现它。 默认行为以模态方式呈现视图控制器。
  • presentViewController:animated:completion:方法总是以模态方式显示视图控制器。 调用此方法的视图控制器可能不会最终处理呈现,但呈现总是模态。 此方法适应水平紧凑环境的呈现风格。

showViewController:sender:和showDetailViewController:sender:方法是启动呈现视图的首选方法。 视图控制器可以在不知道关于视图控制器层次结构的其余部分或当前视图控制器在该层次结构中的位置的任何情况下调用它们。 这些方法还使得更容易在应用程序的不同部分重用视图控制器,而无需编写条件代码路径。

呈现视图控制器

有几种方式来启动视图控制器的呈现:

  • 使用segue自动呈现视图控制器。 segue使用您在Interface Builder中指定的信息实例化并呈现视图控制器。
  • 使用showViewController:sender:或showDetailViewController:sender:方法来显示视图控制器。 在自定义视图控制器中,您可以将这些方法的行为更改为更适合于视图控制器的行为。
  • 调用presentViewController:animated:completion:方法以模态方式呈现视图控制器。

显示视图控制器

当使用showViewController:sender:和showDetailViewController:sender:方法时,在屏幕上获取新的视图控制器的过程是直接的:

  1. 创建要显示的视图控制器对象。 在创建视图控制器时,您有责任使用执行其任务所需的任何数据对其进行初始化。
  2. 将新视图控制器的modalPresentationStyle属性设置为首选显示方式。 此方式可能不会在最终呈现中使用。
  3. 将视图控制器的modalTransitionStyle属性设置为所需的过渡动画方式。 此方式可能不会在最终的动画中使用。
  4. 调用当前视图控制器的showViewController:sender:和showDetailViewController:sender:方法。

UIKit将对showViewController:sender:和showDetailViewController:sender:方法的调用转发到相应的呈现视图控制器。 然后,视图控制器可以决定如何最好地执行呈现,并且可以根据需要改变呈现和转换样式。 例如,导航控制器可以将视图控制器推到其导航堆栈上。

模式地呈现视图控制器

当直接呈现视图控制器时,您可以告诉UIKit如何显示新的视图控制器以及如何在屏幕上动画。

  • 创建要显示的视图控制器对象。
    在创建视图控制器时,您有责任使用执行其任务所需的任何数据对其进行初始化。
  • 将新视图控制器的modalPresentationStyle属性设置为所需的显示样式。
  • 将视图控制器的modalTransitionStyle属性设置为所需的动画样式。
  • 调用当前视图控制器的presentViewController:animated:completion:方法。

调用presentViewController:animated:completion:方法的视图控制器可能不是实际执行模态呈现的视图控制器。 呈现风格确定如何呈现视图控制器,包括呈现视图控制器所需的特性。 例如,全屏显示必须由全屏视图控制器启动。 如果当前呈现视图控制器不合适,UIKit会遍历视图控制器层次结构,直到它找到一个。 完成模态显示后,UIKit将更新受影响的视图控制器的presentingViewController和presentedViewController属性。

清单8-1演示了如何以编程方式呈现视图控制器。 当用户添加新配方时,应用程序通过呈现导航控制器来提示用户关于配方的基本信息。 选择了一个导航控制器,以便有一个标准的地方放置取消和完成按钮。 使用导航控制器还使得将来更容易扩展新的配方界面。 所有你需要做的是在导航堆栈上推新的视图控制器。

清单8-1以编程方式呈现视图控制器

- (void)add:(id)sender {
   // Create the root view controller for the navigation controller
   // The new view controller configures a Cancel and Done button for the
   // navigation bar.
   RecipeAddViewController *addController = [[RecipeAddViewController alloc] init];
 
   addController.modalPresentationStyle = UIModalPresentationFullScreen;
   addController.transitionStyle = UIModalTransitionStyleCoverVertical;
   [self presentViewController:addController animated:YES completion: nil];
}

在弹出中呈现视图控制器

弹出需要额外配置才能显示它们。 将模态表示样式设置为UIModalPresentationPopover后,请配置以下与弹出相关的属性:

  • 将视图控制器的preferredContentSize属性设置为所需的大小。
  • 使用关联的UIPopoverPresentationController对象设置弹出锚点,该对象可以从视图控制器的popoverPresentationController属性访问。 仅设置以下选项之一:
    * 将barButtonItem属性设置为bar按钮项。
    * 将sourceView和sourceRect属性设置为其中一个视图中的特定区域。

您可以使用UIPopoverPresentationController对象根据需要对弹出的外观进行其他调整。 弹出呈现控制器还支持一个委托对象,您可以使用它来响应演示过程中的更改。 例如,您可以使用代理在弹出窗口出现,消失或在屏幕上重新定位时进行响应。

取消呈现的视图控制器

要关闭提交的视图控制器,请调用呈现视图控制器的dismissViewControllerAnimated:completion:方法。 您还可以在呈现的视图控制器本身上调用此方法。 当您在提供的视图控制器上调用该方法时,UIKit自动将请求转发到呈现视图控制器。

在关闭视图控制器之前,始终从视图控制器保存任何重要信息。 取消视图控制器会从视图控制器层次结构中删除它,并从屏幕中删除它的视图。 如果您没有强烈引用存储在其他位置的视图控制器,则关闭它会释放与其关联的内存。

如果呈现的视图控制器必须将数据返回给呈现视图控制器,则使用委托设计模式来促进传送。 委托使得在应用程序的不同部分中重用视图控制器更加容易。 使用委托,所呈现的视图控制器存储对实现来自形式协议的方法的委托对象的引用。 当它收集结果时,呈现的视图控制器在其委托上调用这些方法。 在典型的实现中,呈现视图控制器使其自身成为其呈现的视图控制器的委托。

虽然可以在同一故事板中的视图控制器之间创建段,但是不能在故事板之间创建段。 当要显示存储在不同故事板中的视图控制器时,必须在显示之前显式地实例化该视图控制器,如清单8-2所示。 该示例以模态呈现视图控制器,但您可以将其推送到导航控制器或以其他方式显示它。

清单8-2从故事板加载视图控制器

UIStoryboard* sb = [UIStoryboard storyboardWithName:@"SecondStoryboard" bundle:nil];
MyViewController* myVC = [sb instantiateViewControllerWithIdentifier:@"MyViewController"];
 
// Configure the view controller.
 
// Display the view controller
[self presentViewController:myVC animated:YES completion:nil];

没有要求你在应用程序中创建多个故事板。 这里,虽然,在少数情况下,多个故事板可能是有用的:

  • 你有一个大型编程团队,用户界面的不同部分分配给团队的不同部分。 每个团队在不同的故事板文件中拥有其用户界面的部分,以最小化争用。
  • 你购买或创建了预定义视图控制器类型集合的库; 那些视图控制器的内容在由库提供的故事板中定义。
  • 您的内容需要显示在外部屏幕上。 在这种情况下,您可以将与备用屏幕关联的所有视图控制器保留在单独的故事板中。 同一场景的另一种模式是编写自定义segue。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,026评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,655评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,726评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,204评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,558评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,731评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,944评论 2 314
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,698评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,438评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,633评论 2 247
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,125评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,444评论 3 255
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,137评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,103评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,888评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,772评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,669评论 2 271

推荐阅读更多精彩内容