UIPresentationController是提供高级视图切换的类。它让管理present ViewController的过程变得简单。
先讲一些presentation基础知识,在iPad的设置页面,可以通过popOver弹出一个UIViewController,这个弹出的,可以和用户交互的Controller叫做PresentedViewController,而后面那个被部分遮挡的UIViewController叫做PresentingViewController,而在UIPresentationController中,PresentedViewController是presentation的content,而PresentingViewController叫做Chrome。如下图:
PresentedViewController和PresentingViewControllerContent
所有的UIViewController的presentation都是由UIPresentationController管理的。在UIPresentationController中可以定义content和chrome的动画,可以根据大小的变化来改变content大小,可以根据系统的不同,来改变展示方式,UIPresentationController也是可复用的,可以很容易的拿到其他的UIViewController中去使用。
UIPopoverPresentationController
它在iOS8中替代了UIPopoverController,它在功能上与旧的controller完全等同,并且新增了一些内置的适配特性,可以自动适配iPad与iPhone。以下是新版与旧版接口的比较:
UIPopoverController使用方法:
我们先声明了一个UIViewController作为content controller,使用它初始化了一个UIPopoverController,然后调用presentPopover方法来展示它。这是在iPad上的用法。如果要创建一个在iPad与iPhone上通用的方法,那么需要以下的代码:
我们需要去判断设备是否为iPad,若为iPad,那么创建一个UIPopoverController并展示它,若不是iPad,那么就需要调用常规的presentViewController方法来展示一个UIViewController。
然而我们如果使用UIPopoverPresentationController,那么就不再需要判断设备:
将UIViewController的modalPresentationStyle设置成UIModalPresentationPopover,这个值用来实现popover效果,并且各个平台自动适应。第二行中,通过popoverPresentationController属性来获取它的popoverPresentationController,而不是创建一个新的。然后设置它的一些界面属性,最后调用presentViewController方法来显示这个controller。这样就可以在iPad与iPhone显示自动适应的popover效果了,如下图所示:
iPad效果iPhone效果可见,iPhone上,只是作为一个普通的UITableViewController展示出来。
iPhone上的自适应是在delegate中实现的:
在第一个方法中,指定了UIModelPresentationFullScreen的样式来展示controller。第二个方法中,我们将presentedViewController使用UINavigationController包装起来,使得可以在选中某项之后,通过navigationController提供的一些方法来展示内容,或者后退。
UIAlertView与UIActionSheet
UIAlertView与UIActionSheet都是继承自UIView的,但是它们在实现时,却用了一些UIViewController的方式,并且它的接口比较旧,采用的是delegate方式。在iOS8中,新增了UIAlertController,它可以同时实现Alert和Action Sheets,并且接口采用block方式,它将在应用的同一个window中展示,而不是之前的新window中展示,它还具有和之前的popover controller相同的实现方式,通过presentViewController来展示。下面是新的UIAlertController的用法:
首先创建一个UIAlertController,之后通过addAction方法来增加一些action,而UIAlertAction使用block来设置按钮的点击处理方法。最后,通过调用presentViewController来展示UIAlertController。
UISearchDisplayController
search在iOS中包含两部分:UISearchBar与UISearchDisplayController。它们都是很古老的接口,功能与样式都不能满足现状的应用,UISearchDisplayController的配置项很少,它只能在tableView中显示结果,而不能在collectionView或者mapView中显示。它的present过程只是通过addSubview来将view作为一个子view添加上去。而如果它的父view是一个scrollView,那么手势处理就会有冲突。在iOS8中,引入了UISearchController,它允许presentingController是任意类型的,不一定是全屏幕的,search bar animation可以自定义,并且可以在不同平台上适配。
在之前的接口中,我们使用UISearchDisplayController来实现search功能:
首先初始化一个UISearchBar,再用它初始化一个UISearchDisplayController,指定controller的searchResuleDataSource与searchResultDelegate,之后,将searchBar作为当前view中的tableView的tableHeaderView来显示。而在iOS8中,实现方式是这样的:
首先初始化一个自定义的resultsController,可以是一个collectionView,也可以是一些其他的自定义样式。之后使用这个resultsController创建一个UISearchController,指定searchController的searchResultsUpdater为resultsController,之后将searchBar加到tableView的tableHeaderView上,最后,设置当前Controller的definesPresentationContext为YES,表示UISearchController在present时,可以覆盖当前controller。
经过这样的修改,所有的都变成了Controller,不再有UIView组件,也不再需要通过创建新window来展示UIView,更加容易控制。UIPresentationController为Content与Chrome提供了一个很好的抽象,并且在iPad与iPhone间,自动适应使得编码更简洁。
**********************************
1.回顾UIPopoverController的使用,下面这份代码只能在ipad下运行
// 初始化控制器,SecondViewController类继承自UIViewController
SecondViewController *vc = [[SecondViewController alloc] init];
// 把vc包装成UIPopoverController
UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:vc];
// 设置popover的指向,
// 指向当前控制上button按钮,所以FromRect后跟bounds
// 如果是指向当前控制的View,则FromRect后跟frame
[popover presentPopoverFromRect:self.button.bounds inView:self.button permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
2. 运用UIPopoverPresentationController,下面这份代码在iphone和ipad中,都可以正常运行
2.1 在iphone中是常见的modal方式,也就是从屏幕底部爬上来,而在ipad中,是popover的那种方式
// 初始化控制器
SecondViewController *vc = [[SecondViewController alloc] init];
// modal出来是个popover
vc.modalPresentationStyle = UIModalPresentationPopover;
// 取出vc所在的UIPopoverPresentationController
vc.popoverPresentationController.sourceView = self.button;
vc.popoverPresentationController.sourceRect = self.button.bounds;
[self presentViewController:vc animated:YES completion:nil];
2.2 在iphone中,上面这份代码等同于下面:
SecondViewController *vc = [[SecondViewController alloc] init];
/* 相当于中间3行代码不存在
vc.modalPresentationStyle = UIModalPresentationPopover;
vc.popoverPresentationController.sourceView = self.button;
vc.popoverPresentationController.sourceRect = self.button.bounds;
*/
[self presentViewController:vc animated:YES completion:nil];
2.3 苹果在iOS8中对UIViewController做了类扩展
也就是说popoverPresentationController是UIViewController的属性
modalPresentationStyle是UIViewController成员变量
UIPopoverPresentationController继承自UIPresentationController, UIPresentationController又继承自NSObject