自动转屏,UIPopoverController与模态视图控制器

UIPopoverController请介绍新版

如果需要修改默认支持方向,则必须在相应的UIViewController中覆盖supportedInterfaceOrientations方法。

在许多应用中,UINavigationController和UITabViewController是出现频率最高的两种视图控制器。UINavigationController使用继承自UIViewController的supportedInterfaceOrientations。如果需要由UINavigationController当前显示的视图控制器来决定所支持的界面方向,则可以创建UINavigationController的子类并覆盖supportedInterfaceOrientations方法。

UITabViewController则会依次检查每个标签项所支持的界面方向,然后在自身的supportedInterfaceOrientations方法中返回所有标签项都支持的界面方向。

-(NSUInteger)supportedInterfaceOrientations 
{
    return self.topViewController.supportedInterfaceOrientations;  
}

如果需要在界面方向发生变化时执行某些操作,则可以在UIViewController中覆盖willAnimateRotationToInterfaceOrientation:duration:方法。在界面方向发生改变后,UIViewController会收到willAnimateRotationToInterfaceOrientation: duration:消息,消息的第一个参数是新的界面方向。如果在应用转屏时不需要对视图做处理,或者不需要使用属性变换的动画效果,也可以将该方法替换为willRotateToInterfaceOrientation:duration:。两个方法将会在转屏时同时调用,参数的含义也都是相同的。但是,willRotateToInterfaceOrientation:duration:方法中不会自动添加任何动画效果。

如果需要在转屏完成之后执行一些操作,则可以在UIViewController中覆盖didRotateFromInterfaceOrientation:方法。该方法的参数是发生转屏之前的界面方向。最后,UIViewController对象有一个interfaceOrientation属性,表示该对象的当前界面方向。

UIPopoverController

为了有效利用充足的屏幕空间,Apple针对iPad应用提供了UIPopoverController。在iPhone应用中,如果要让用户做一个选择(例如在照片库中选择一张照片),或者针对屏幕上的某些元素显示相关摘要信息(例如向用户解释某一项数据的具体含义),则可能会使用模态视图控制器或警告视图;而在iPad应用中,这些场景更适合使用UIPopoverController。

UIPopoverController能够在一个带边框的窗口中显示一个指定的视图控制器的视图。此外,这个窗口会“悬浮”在其他界面的前面。创建UIPopoverController对象时需要设置contentViewController属性,指向需要显示的视图控制器。

模态视图控制器

要关闭某个以模态形式显示的视图控制器,必须向负责显示该对象的视图控制器发送dismissViewControllerAnimated:completion:
  UIViewController对象有一个名为presentingViewController的属性,当某个UIViewController对象以模态形式显示时,该属性会指向显示该对象的那个UIViewController对象。
  在iPhone或iPodtouch中以模态形式显示视图控制器时,视图控制器的视图会占据整个窗口。对iPhone系设备,这是默认的样式,也是唯一的选择。对iPad则有两个额外的选项:表单样式(formsheet)和页单样式(pagesheet)。修改视图控制器的modalPresentationStyle属性,可以改变其在模态形式下的外观。该属性的类型是UIModalPresentationStyle,其值可以是UIModalPresentationFormSheet或UIModalPresentationPageSheet两个常量中的一个。
修改模态样式后,UINavigationController对象不会占据整个屏幕,底下的对象的视图也不会消失。关闭模态视图控制器后,底下对象不会收到viewWillAppear:消息和viewDidAppear:消息,因此也没有机会刷新底下对象。为了能够在模态视图控制器被关闭后立刻执行这行代码,可以使用视图控制器的dismissViewControllerAnimated:completion:方法。

//类似C函数,Block对象也有返回值和一组实参,必须在声明Block对象时一并列出。以dismissBlock属性所指向的Block对象为例,其返回值是void,并且没有任何实参。
@property(nonatomic,copy)void(^dismissBlock)(void);

视图控制器有一个名为modalTransitionStyle的属性,该属性的类型是UIModalTransitionStyle:
UIModalTransitionStyleCoverVertical从底部滑入  UIModalTransitionStyleCrossDissolve淡入  UIModalTransitionStyleFlipHorizontal以3D效果翻转  UIModalTransitionStylePartialCurl模拟书页卷角

线程安全的单例

为了确保在多线程应用中只创建一次对象,可以使用dispatch_once()创建线程安全的单例(thread-safe singleton)。

static dispatch_once_t onceToken;  
dispatch_once(&onceToken,^{
.......
 });
位掩码

如何使用单一值描述多种可能值?答案是位掩码(bitmasks)
使用位掩码可以避免为保存每一种可能值而创建大量的属性.
 二进制数字中的列称为二进制位(bit)。可以将二进制位想象成开关,1代表“开”,0代表“关”。这样就可以将int类型的整数(至少会占用32个二进制位)想成是一组开关。数字的每个位代表一个“开关”:1代表“开(真)”,0代表“关(假)”。这等于是将很多布尔值塞进了一个整数。

视图控制器之间的关系

视图控制器之间的关系可以分为两类:父子关系和显示被显示关系。

当使用视图控制器容器(viewcontrollercontainer)时,就会产生拥有父子关系的视图控制器。
UINavigationController对象、UITabBarController对象和UISplitViewController对象都是视图控制器容器。这些容器的共性是都有一个类型为数组对象的viewControllers属性,用于保存一组视图控制器。

无论哪种视图控制器容器,都是UIViewController的子类对象,因此也有一个名为view的属性。视图控制器容器的特性是:容器对象会将viewControllers中的视图作为子视图加入自己的视图。此外,容器对象通常都会有自己的默认外观。以UINavigationController对象为例,它会在其视图顶部显示一个UINavigationBar对象,然后在余下的空间中显示topViewController的视图。

视图控制器族系示例

任何容器对象都可以通过viewControllers访问其子对象,而子对象也可以通过UIViewController对象的四个特定属性来访问其容器对象。
先介绍这四个特定属性的前三个,这三个属性分别是:navigationController、?

tabBarController和splitViewController。当某个视图控制器收到navigationController消息、tabBarController消息或splitViewController消息后,就会沿着族系向上查找,直到找到类型匹配的视图控制器容器。如果没有找到,相应的方法就会返回nil。

然后介绍第四个属性。UIViewController有一个名为parentViewController的属性。该属性会指向族系中“最近”的那个容器对象。因此,根据族系的形成方式,parentViewController可能会指向UINavigationController对象、UITabBarController对象或UISplitViewController对象。

视图控制器的另一类关系是显示被显示关系(presentingpresenterrelationship)。当某个视图控制器以模态形式显示另一个视图控制器时,就会产生拥有这种关系的视图控制器。当某个视图控制器(A)以模态形式显示另一个视图控制器(B)时,B的视图会覆盖A的视图。此外,任何一个UIViewController对象都可以以模态的形式显示另一个视图控制器

通过UIViewController对象的presentingViewController属性和presentedViewController属性,可以得到指向相应视图控制器的指针。当某个视图控制器(A)以模态形式显示另一个视图控制器(B)时,A的presentedViewController会指向B,而B的presentingViewController属性会指向A:


显示-被显示关系
显示被显示关系

在显示被显示关系中,位于关系两头的视图控制器不会处于同一个族系中。被显示的视图控制器会有自己的族系,这个族系可以只有一个UIViewController对象,也可以由多个UIViewController对象组成。


视图控制器的层次结构示例

凡是针对父子关系的属性,其指向的对象都会在当前族系的范围内。因此,向族系2中的视图控制器发送tabBarController消息,并不会返回族系1中的UITabBarController对象,而会返回nil。
不同族系中的视图控制器的关系稍微复杂一些。当应用以模态形式显示某个视图控制器时,负责显示该视图控制器的将是相关族系中的顶部视图控制器(或者可以说“最老”的那个)。
上图中的对象为例,族系2中的视图控制器的presentingViewController属性指向的都是UITabBarController对象。无论应用是向族系1中的哪个视图控制器发送presentViewController:animated:completion:消息,负责显示的对象始终是UITabBarController对象。

对某个族系中的所有视图控制器,其presentingViewController属性和presentedViewController属性都是有效的,并且总会指向另一个族系中的顶部对象。
 通过编写代码,可以改变这种“顶部对象负责以模态形式显示其他视图控制器”的行为(只能在iPad中使用),这样就可以限定视图的显示位置。

可以要求包含了该对象的UINavigationController对象显示在UITableView对象上,从而避免覆盖UINavigationBar。

为此,UIViewController提供了definesPresentationContext属性,其默认值是NO。当某个视图控制器的definesPresentationContext是NO时,会将“显示权(presentationoff)”传递给父视图控制器,并沿着族系依次向上传递,直到最顶层视图控制器。也就是说,最后会由最顶层视图控制器负责显示新的视图控制器;相反,在传递过程中,如果某个视图控制器的definesPresentationContext是YES,该视图控制器就不会再将“显示权”传递给父视图控制器,而是由自己负责显示新的视图控制器(见下图)。此外,对后面这种情况(视图应该不会覆盖UINavigationBar对象),必须将需要显示的视图控制器的modalPresentationStyle 属性设置为UIModalPresentationCurrentContext。


definesPresentationContext属性为YES的示例
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,826评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,968评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,234评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,562评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,611评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,482评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,271评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,166评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,608评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,814评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,926评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,644评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,249评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,866评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,991评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,063评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,871评论 2 354

推荐阅读更多精彩内容