SlideShare una empresa de Scribd logo
1 de 31
Descargar para leer sin conexión
通知和翻转




范圣刚,princetoad@gmail.com, www.tfan.org
• Objective-C 代码都是有关 objects 发送 messages
 给其他的 objects。这个通讯⼀一般是发⽣生在两个
 object 之间,但是有时候⼀一堆 objects 都关⼼心⼀一个
 object

• 他们都想知道这个对象什么时候在做⼀一些它们感
 兴趣的事,⽽而由这个 object 来给每⼀一个感兴趣的
 object 来发送消息⼜又不可⾏行
• 相反,⼀一个对象可以发布关于它们正在做什么的
 通知给⼀一个中央通知中⼼心。感兴趣的对象进⾏行注
 册以在特定通知被发布的时候接收⼀一个消息,或
 者当⼀一个特定的对象进⾏行了发布

• 这个章节我们将会学习如何使⽤用 notification
 center 来处理 notification,同时我们也会学习有
 关 UIViewController 的⾃自动翻转特性
通知中⼼心 (Notification Center)
• 每个应⽤用程序都有⼀一个 NSNotificationCenter 的实
 例,它就像⼀一个智能布告栏

• ⼀一个对象可以作为⼀一个观察者注册(“”Send me
 ‘lost dog’ notification)

• 当另⼀一个对象发布了⼀一个通知(“I lost my dog”),
 notification center 就会转发这个通知给已注册观
 察者
NSNotification
NSNotification
• 这些 Notifications 都是 NSNotification 的实例
• 每个 NSNotification 对象都有⼀一个 name,以及⼀一
 个回指到发布它的对象的指针 object
• 当你注册为⼀一个观察者时,你可以指定⼀一个
 notification name,⼀一个 posting object,以及当⼀一
 个符合条件的通知发布时发送给你的 message
name 和 object
• 下⾯面的代码⽚片段为名为 LostDog ,发布者可以是任意
 对象的通知⽽而注册
• 当⼀一个对象发布了⼀一个 LostDog 通知,将会有⼀一个
 retrieveDog: 消息发给你
• 注意 nil 在这⾥里的作⽤用是通配符,也可以把 nil 作为
 name 的参数,这样会不管它的名称⽽而把所有的通知
 都给你
• 把 notification name 和 posting object 都设成 nil ,你
 将会收到所有的通知
 NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
 [nc addObserver:self                    // 将会发给对象 self
        selector:@selector(retrieveDog:) // retrieveDog:
            name:@"LostDog"              // 当 @"LostDog" 被发布,发布者可以是
          object:nil];                   // 任意对象
作为参数的 NSNotification
• 当通知到达时被触发的⽅方法采⽤用⼀一个
 NSNotification 对象作为参数

- (void)retrieveDog:(NSNotification *)note
{
    id poster = [note object];
    NSString *name = [note name];
    NSDictionary *extraInformation = [note userInfo];
}
userInfo
   • notification 对象也可以具有⼀一个附加到它上⾯面的
     userInfo dictionary,这个 dictionary 被⽤用来传递附
     加信息,例如对找到的狗的⼀一些描述
   • 另外⼀一个实际开发中的例⼦子,当 keyboard 出现在
     屏幕上的时候,它发布⼀一个包含 userInfo 的
     UIKeyboardDidShowNotification 。这个 userInfo
     dictionary 包含的是新的可⻅见键盘所占的屏幕区域

NSDictionary *extraInfo = [NSDictionary dictionaryWithObject:@"Fido"
forKey:@"Name"];
NSNotification *note = [NSNotification notificationWithName:@"LostDog"
                                                             object:self
                                                           userInfo:extraInfo];
[[NSNotificationCenter defaultCenter] postNotification:note];
观察者的强引⽤用
• notification center 保存对它的观察者们的强引⽤用
• 如果对象在它被销毁前没有把它⾃自⾝身作为观察者
  移除,那么下次在它注册的⼀一个通知发布的时
  候,中⼼心会尝试发给对象⼀一个消息。因为对象已
  经不存在了,应⽤用程序将会 crash
• 所以,如果⼀一个对象在通知中⼼心注册了,那么这
  个对象必须在它的 dealloc ⽅方法中取消注册
  (unregister)
- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}
UIDevice 通知
• ⼀一个经常发布通知的对象是 UIDevice
• 这⾥里是作为 UIDevice 发布的通知的名称的常量:
• UIDeviceOrientationDidChangNotification
• UIDeviceBatteryStateDidChangeNotification
• UIDeviceBatteryLevelDidChangeNotification
• UIDeviceProximityStateDidChangeNotification
• 从上⾯面这些通知名称我们可以看到,我们可以在
⼿手机屏幕翻转,距离我们⾯面部很近时,以及电量
(等跟设备相关的信息)发⽣生变化的情况下得到
通知
HeavyRotation 项⺫⽬目
• 新建⼀一个 Empty Application 项⺫⽬目,命名为
 HeavyRotation
• 输⼊入 Rotation 作为 Class Prefix
• iPhone 作为 Device Family
• 仅勾选“Use Automatic Reference Counting”
注册 UIDeviceOrientationDidChangeNotification
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:
(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.

    // 得到设备对象
    UIDevice *device = [UIDevice currentDevice];

    // 请设备开始监视 orientation 的 accelerometer
    [device beginGeneratingDeviceOrientationNotifications];

    // 得到 app 的 notification center
    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];

    // 把⾃自⼰己添加为观察者
    [nc addObserver:self
           selector:@selector(orientationChanged:)
               name:UIDeviceOrientationDidChangeNotification
             object:device];

    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];
    return YES;
}
实现通知消息(⽅方法)
• 这样当设备的 orientation 变更时,
 orientationChanged: 消息就会被发送给
 RotationAppDelegate 的实例
• 在同⼀一个⽂文件中添加 orientationChanged: ⽅方法
 - (void)orientationChanged:(NSNotification *)note
 {
     NSLog(@"orientationChanged: %d", [[note object] orientation]);
 }
UIDeviceOrientation

typedef NS_ENUM(NSInteger, UIDeviceOrientation) {
     UIDeviceOrientationUnknown,
     UIDeviceOrientationPortrait,           // Device   oriented vertically,
home button on the bottom
     UIDeviceOrientationPortraitUpsideDown, // Device   oriented vertically,
home button on the top
     UIDeviceOrientationLandscapeLeft,      // Device   oriented horizontally,
home button on the right
     UIDeviceOrientationLandscapeRight,     // Device   oriented horizontally,
home button on the left
     UIDeviceOrientationFaceUp,             // Device   oriented flat, face up
     UIDeviceOrientationFaceDown            // Device   oriented flat, face
down
};
能够发布通知的⼀一些类
• 注意消息后⾯面的冒号是⽅方法名称的⼀一部分 -
orientationChanged:
• 可以发布通知的⼀一些类:
• UIApplication
• NSManagedObjectContext
• MPMoviePlayerController
• NSFileHandle
• UIWindow
• UITextField
• UITextView
⾃自动翻转 - Autorotation
• 很多应⽤用程序在⽤用户旋转设备的时候会把所有的
 视图旋转并调整⼤大⼩小

• 我们可以使⽤用 UIDevice notification 来实现这个,
 但这会是⼀一个很⼤大量的⼯工作。幸运的是,我们可
 以使⽤用 autorotation 来简化这个过程
• 如果屏幕上的视图通过⼀一个 view controller 被控
 制,当设备被翻转时,这个 view controller 会被询
 问是否可以翻转 view 。如果 view controller 同意
 的话,view 被调整⼤大⼩小并且翻转。所有的
 subviews 也被调整⼤大⼩小和翻转
HeavyViewController
• 我们实现⼀一个 UIViewController 的⼦子类来获得⾃自动
 翻转特性。这个 view controller 的 view 会拥有
 subviews,所以我们使⽤用带 XIB ⽂文件的
 UIViewController 模版来创建这个类
• 选择 File -> New -> File..., 从 iOS 部分,选择 Cocoa
 Touch, 选择 Objective-C 类模版
• 命名⼦子类为 HeavyViewController, 选择
 UIViewController 作为超类,勾选 “With XIB for user
 interface”
实现 autorotation
• 这样我们就有了⼀一个名为 HeavyViewController 的
 UIViewController ⼦子类
• 同时也有了⼀一个名为 HeavyViewController.xib 的
 XIB ⽂文件
• 这个 XIB ⽂文件有⼀一个类型是 HeavyViewController
 的 File’s Owner, 它的 view outlet 被连接到了⼀一个
 320x460(548)点⼤大⼩小的 view 对象
• 要在 HeavyRotation 中实现 autorotation,我们需
 要做下⾯面两个⼯工作:
 • 在 HeavyViewController 中重写
  shouldAutorotateToInterfaceOrientation: 以允许
  autorotation

 • 针对每个 subview ⼩小⼼心的设置 autoresize mask 以在
  superview 被调整到填充被翻转的窗⼝口时表现合理
设备翻转:iPhone 和 iPad
• 当设备翻转时,当前显⽰示在屏幕上的 view 的 view
 controller 将被发送⼀一个
 shouldAutorotationToInterfaceOrientation: 消息。这
 个⽅方法返回⼀一个 BOOL 来标明是否可以翻转这个
 view controller 的 view
设备翻转:iPhone 和 iPad
 • 对于 iPhone 应⽤用⽽而⾔言,我们⼀一般允许 right-side
    up(正⽴立), landscape left(平放左边在上), 和
    landscape right(平放右边在上);在 iPad 上,⼀一
    般允许全部⽅方向,包括 upside-down(倒⽴立)
 • 我们在 HeavyViewController.m 中,为两种常⻅见的
    iPhone 朝向返回 YES
- (BOOL)shouldAutorotateToInterfaceOrientation:
(UIInterfaceOrientation)toInterfaceOrientation
{
    return (toInterfaceOrientation == UIInterfaceOrientationPortrait)
    || UIInterfaceOrientationIsLandscape(toInterfaceOrientation);
}
HeavyViewController XIB 布局
• 增加⼀一些内容来翻转
• 拖⼀一张图⽚片到 project
 navigator 中

• 打开
 HeavyViewController.xi
 b, 在 view 上放⼀一个
 slider,⼀一个 image
 view,两个 button
UIImageView 属性
• 设置 UIImageView 的
 属性为刚才的图⽚片⽂文
 件,设置 Mode 为
 Aspect Fit,设置背景颜
 ⾊色为 Light Gray
autoresizing mask
• 当设备翻转时,⾸首先 view 被翻转到和设备的朝向
 对⻬齐;其次 view 的⼤大⼩小被调整到适合屏幕
• 在 portrait 模式下的 320 宽和 480 ⾼高的 view 将变
 成 480 宽和 320 ⾼高的 landscape 模式
• 当 view 被调整⼤大⼩小时,它将 autoresize 它的所有
 subview
• 每个 subview 被根据它的 autosizing mask 属性进
 ⾏行调整
• 可以通过在 XIB ⽂文件中选择⼀一个 view,然后在
 size inspector 中编辑 autoresizing mask
Autoresizing 设置
• image view 应该保持在中间位置
• 滑块应该变宽,和 superview 的顶部保持固定距
 离,并且和左右边界保持同样距离
• 两个按钮应该停留在它们相应的 corner 并且不⾃自
 动调整⼤大⼩小
设成 rootViewController
    • 创建⼀一个 HeavyViewController 的实例,并且把它
     设置成 window 的 rootViewController
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen]
bounds]];
    // Override point for customization after application launch.
    UIDevice *device = [UIDevice currentDevice];
    [device beginGeneratingDeviceOrientationNotifications];
    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
    [nc addObserver:self
           selector:@selector(orientationChanged:)
               name:UIDeviceOrientationDidChangeNotification
             object:device];

     HeavyViewController *hvc = [[HeavyViewController alloc] init];
     [[self window] setRootViewController:hvc];

     self.window.backgroundColor = [UIColor whiteColor];
     [self.window makeKeyAndVisible];
     return YES;
}

Más contenido relacionado

Similar a 08 Notification and Rotation

07 View Controllers
07 View Controllers07 View Controllers
07 View ControllersTom Fan
 
11 UINavigationController
11 UINavigationController11 UINavigationController
11 UINavigationControllerTom Fan
 
Html5移动网站开发实践
Html5移动网站开发实践Html5移动网站开发实践
Html5移动网站开发实践Web Zhao
 
01 A Simple iOS Application
01 A Simple iOS Application01 A Simple iOS Application
01 A Simple iOS ApplicationTom Fan
 
设计师转型培训-工具篇
设计师转型培训-工具篇设计师转型培训-工具篇
设计师转型培训-工具篇Robert Luo
 
14 Saving Loading and Application States
14 Saving Loading and Application States14 Saving Loading and Application States
14 Saving Loading and Application StatesTom Fan
 
09 UITableView and UITableViewController
09 UITableView and UITableViewController09 UITableView and UITableViewController
09 UITableView and UITableViewControllerTom Fan
 
為什麼 App 卡卡的
為什麼 App 卡卡的為什麼 App 卡卡的
為什麼 App 卡卡的鈺翔 林
 
10 Editing UITableView
10 Editing UITableView10 Editing UITableView
10 Editing UITableViewTom Fan
 
掌星 移动互联网开发笔记-Vol001
掌星 移动互联网开发笔记-Vol001掌星 移动互联网开发笔记-Vol001
掌星 移动互联网开发笔记-Vol001rainx1982
 
iOS App 開發 -- Storybard 基礎練習、APP 上架、IAP
iOS App 開發 -- Storybard 基礎練習、APP 上架、IAPiOS App 開發 -- Storybard 基礎練習、APP 上架、IAP
iOS App 開發 -- Storybard 基礎練習、APP 上架、IAPMing-Sian Lin
 
Voice Recognization in Android
Voice Recognization in AndroidVoice Recognization in Android
Voice Recognization in Androidrogeryi
 
Motion and gesture in Android
Motion and gesture in AndroidMotion and gesture in Android
Motion and gesture in Androidrogeryi
 
KISSY_Component
KISSY_ComponentKISSY_Component
KISSY_Componentyiming he
 

Similar a 08 Notification and Rotation (20)

07 View Controllers
07 View Controllers07 View Controllers
07 View Controllers
 
11 UINavigationController
11 UINavigationController11 UINavigationController
11 UINavigationController
 
Html5移动网站开发实践
Html5移动网站开发实践Html5移动网站开发实践
Html5移动网站开发实践
 
01 A Simple iOS Application
01 A Simple iOS Application01 A Simple iOS Application
01 A Simple iOS Application
 
I os 10
I os 10I os 10
I os 10
 
设计师转型培训-工具篇
设计师转型培训-工具篇设计师转型培训-工具篇
设计师转型培训-工具篇
 
14 Saving Loading and Application States
14 Saving Loading and Application States14 Saving Loading and Application States
14 Saving Loading and Application States
 
09 UITableView and UITableViewController
09 UITableView and UITableViewController09 UITableView and UITableViewController
09 UITableView and UITableViewController
 
為什麼 App 卡卡的
為什麼 App 卡卡的為什麼 App 卡卡的
為什麼 App 卡卡的
 
10 Editing UITableView
10 Editing UITableView10 Editing UITableView
10 Editing UITableView
 
掌星 移动互联网开发笔记-Vol001
掌星 移动互联网开发笔记-Vol001掌星 移动互联网开发笔记-Vol001
掌星 移动互联网开发笔记-Vol001
 
iOS App 開發 -- Storybard 基礎練習、APP 上架、IAP
iOS App 開發 -- Storybard 基礎練習、APP 上架、IAPiOS App 開發 -- Storybard 基礎練習、APP 上架、IAP
iOS App 開發 -- Storybard 基礎練習、APP 上架、IAP
 
View Animation
View AnimationView Animation
View Animation
 
Voice Recognization in Android
Voice Recognization in AndroidVoice Recognization in Android
Voice Recognization in Android
 
Motion and gesture in Android
Motion and gesture in AndroidMotion and gesture in Android
Motion and gesture in Android
 
Ios
IosIos
Ios
 
KISSY_Component
KISSY_ComponentKISSY_Component
KISSY_Component
 
I os 02
I os 02I os 02
I os 02
 
005
005005
005
 
I os 16
I os 16I os 16
I os 16
 

Más de Tom Fan

PhoneGap 通信原理和插件系统
PhoneGap 通信原理和插件系统PhoneGap 通信原理和插件系统
PhoneGap 通信原理和插件系统Tom Fan
 
HTML5 Web workers
HTML5 Web workersHTML5 Web workers
HTML5 Web workersTom Fan
 
Web sockets
Web socketsWeb sockets
Web socketsTom Fan
 
Semantics
SemanticsSemantics
SemanticsTom Fan
 
Multimedia
MultimediaMultimedia
MultimediaTom Fan
 
Intro to-html5
Intro to-html5Intro to-html5
Intro to-html5Tom Fan
 
Html5 history
Html5 historyHtml5 history
Html5 historyTom Fan
 
Geolocation
GeolocationGeolocation
GeolocationTom Fan
 
File api
File apiFile api
File apiTom Fan
 
Deviceaccess
DeviceaccessDeviceaccess
DeviceaccessTom Fan
 
Webstorage
WebstorageWebstorage
WebstorageTom Fan
 
Html5 最重要的部分
Html5 最重要的部分Html5 最重要的部分
Html5 最重要的部分Tom Fan
 
AT&T 的 HTML5 策略和应用现状
AT&T 的 HTML5 策略和应用现状AT&T 的 HTML5 策略和应用现状
AT&T 的 HTML5 策略和应用现状Tom Fan
 
PhoneGap 2.0 开发
PhoneGap 2.0 开发PhoneGap 2.0 开发
PhoneGap 2.0 开发Tom Fan
 
Android 平台 HTML5 应用开发
Android 平台 HTML5 应用开发Android 平台 HTML5 应用开发
Android 平台 HTML5 应用开发Tom Fan
 
HTML5 生态系统和应用架构模型
HTML5 生态系统和应用架构模型HTML5 生态系统和应用架构模型
HTML5 生态系统和应用架构模型Tom Fan
 
18 NSUserDefaults
18 NSUserDefaults18 NSUserDefaults
18 NSUserDefaultsTom Fan
 
17 Localization
17 Localization17 Localization
17 LocalizationTom Fan
 

Más de Tom Fan (20)

PhoneGap 通信原理和插件系统
PhoneGap 通信原理和插件系统PhoneGap 通信原理和插件系统
PhoneGap 通信原理和插件系统
 
HTML5 Web workers
HTML5 Web workersHTML5 Web workers
HTML5 Web workers
 
Web sockets
Web socketsWeb sockets
Web sockets
 
Storage
StorageStorage
Storage
 
Semantics
SemanticsSemantics
Semantics
 
Multimedia
MultimediaMultimedia
Multimedia
 
Intro to-html5
Intro to-html5Intro to-html5
Intro to-html5
 
Html5 history
Html5 historyHtml5 history
Html5 history
 
Geolocation
GeolocationGeolocation
Geolocation
 
File api
File apiFile api
File api
 
Deviceaccess
DeviceaccessDeviceaccess
Deviceaccess
 
Css3
Css3Css3
Css3
 
Webstorage
WebstorageWebstorage
Webstorage
 
Html5 最重要的部分
Html5 最重要的部分Html5 最重要的部分
Html5 最重要的部分
 
AT&T 的 HTML5 策略和应用现状
AT&T 的 HTML5 策略和应用现状AT&T 的 HTML5 策略和应用现状
AT&T 的 HTML5 策略和应用现状
 
PhoneGap 2.0 开发
PhoneGap 2.0 开发PhoneGap 2.0 开发
PhoneGap 2.0 开发
 
Android 平台 HTML5 应用开发
Android 平台 HTML5 应用开发Android 平台 HTML5 应用开发
Android 平台 HTML5 应用开发
 
HTML5 生态系统和应用架构模型
HTML5 生态系统和应用架构模型HTML5 生态系统和应用架构模型
HTML5 生态系统和应用架构模型
 
18 NSUserDefaults
18 NSUserDefaults18 NSUserDefaults
18 NSUserDefaults
 
17 Localization
17 Localization17 Localization
17 Localization
 

08 Notification and Rotation

  • 2. • Objective-C 代码都是有关 objects 发送 messages 给其他的 objects。这个通讯⼀一般是发⽣生在两个 object 之间,但是有时候⼀一堆 objects 都关⼼心⼀一个 object • 他们都想知道这个对象什么时候在做⼀一些它们感 兴趣的事,⽽而由这个 object 来给每⼀一个感兴趣的 object 来发送消息⼜又不可⾏行
  • 3. • 相反,⼀一个对象可以发布关于它们正在做什么的 通知给⼀一个中央通知中⼼心。感兴趣的对象进⾏行注 册以在特定通知被发布的时候接收⼀一个消息,或 者当⼀一个特定的对象进⾏行了发布 • 这个章节我们将会学习如何使⽤用 notification center 来处理 notification,同时我们也会学习有 关 UIViewController 的⾃自动翻转特性
  • 5. • 每个应⽤用程序都有⼀一个 NSNotificationCenter 的实 例,它就像⼀一个智能布告栏 • ⼀一个对象可以作为⼀一个观察者注册(“”Send me ‘lost dog’ notification) • 当另⼀一个对象发布了⼀一个通知(“I lost my dog”), notification center 就会转发这个通知给已注册观 察者
  • 7. NSNotification • 这些 Notifications 都是 NSNotification 的实例 • 每个 NSNotification 对象都有⼀一个 name,以及⼀一 个回指到发布它的对象的指针 object • 当你注册为⼀一个观察者时,你可以指定⼀一个 notification name,⼀一个 posting object,以及当⼀一 个符合条件的通知发布时发送给你的 message
  • 8. name 和 object • 下⾯面的代码⽚片段为名为 LostDog ,发布者可以是任意 对象的通知⽽而注册 • 当⼀一个对象发布了⼀一个 LostDog 通知,将会有⼀一个 retrieveDog: 消息发给你 • 注意 nil 在这⾥里的作⽤用是通配符,也可以把 nil 作为 name 的参数,这样会不管它的名称⽽而把所有的通知 都给你 • 把 notification name 和 posting object 都设成 nil ,你 将会收到所有的通知 NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; [nc addObserver:self // 将会发给对象 self selector:@selector(retrieveDog:) // retrieveDog: name:@"LostDog" // 当 @"LostDog" 被发布,发布者可以是 object:nil]; // 任意对象
  • 9. 作为参数的 NSNotification • 当通知到达时被触发的⽅方法采⽤用⼀一个 NSNotification 对象作为参数 - (void)retrieveDog:(NSNotification *)note { id poster = [note object]; NSString *name = [note name]; NSDictionary *extraInformation = [note userInfo]; }
  • 10. userInfo • notification 对象也可以具有⼀一个附加到它上⾯面的 userInfo dictionary,这个 dictionary 被⽤用来传递附 加信息,例如对找到的狗的⼀一些描述 • 另外⼀一个实际开发中的例⼦子,当 keyboard 出现在 屏幕上的时候,它发布⼀一个包含 userInfo 的 UIKeyboardDidShowNotification 。这个 userInfo dictionary 包含的是新的可⻅见键盘所占的屏幕区域 NSDictionary *extraInfo = [NSDictionary dictionaryWithObject:@"Fido" forKey:@"Name"]; NSNotification *note = [NSNotification notificationWithName:@"LostDog" object:self userInfo:extraInfo]; [[NSNotificationCenter defaultCenter] postNotification:note];
  • 11. 观察者的强引⽤用 • notification center 保存对它的观察者们的强引⽤用 • 如果对象在它被销毁前没有把它⾃自⾝身作为观察者 移除,那么下次在它注册的⼀一个通知发布的时 候,中⼼心会尝试发给对象⼀一个消息。因为对象已 经不存在了,应⽤用程序将会 crash • 所以,如果⼀一个对象在通知中⼼心注册了,那么这 个对象必须在它的 dealloc ⽅方法中取消注册 (unregister) - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; }
  • 13. • ⼀一个经常发布通知的对象是 UIDevice • 这⾥里是作为 UIDevice 发布的通知的名称的常量: • UIDeviceOrientationDidChangNotification • UIDeviceBatteryStateDidChangeNotification • UIDeviceBatteryLevelDidChangeNotification • UIDeviceProximityStateDidChangeNotification • 从上⾯面这些通知名称我们可以看到,我们可以在 ⼿手机屏幕翻转,距离我们⾯面部很近时,以及电量 (等跟设备相关的信息)发⽣生变化的情况下得到 通知
  • 14. HeavyRotation 项⺫⽬目 • 新建⼀一个 Empty Application 项⺫⽬目,命名为 HeavyRotation • 输⼊入 Rotation 作为 Class Prefix • iPhone 作为 Device Family • 仅勾选“Use Automatic Reference Counting”
  • 15. 注册 UIDeviceOrientationDidChangeNotification - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; // Override point for customization after application launch. // 得到设备对象 UIDevice *device = [UIDevice currentDevice]; // 请设备开始监视 orientation 的 accelerometer [device beginGeneratingDeviceOrientationNotifications]; // 得到 app 的 notification center NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; // 把⾃自⼰己添加为观察者 [nc addObserver:self selector:@selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:device]; self.window.backgroundColor = [UIColor whiteColor]; [self.window makeKeyAndVisible]; return YES; }
  • 16. 实现通知消息(⽅方法) • 这样当设备的 orientation 变更时, orientationChanged: 消息就会被发送给 RotationAppDelegate 的实例 • 在同⼀一个⽂文件中添加 orientationChanged: ⽅方法 - (void)orientationChanged:(NSNotification *)note { NSLog(@"orientationChanged: %d", [[note object] orientation]); }
  • 17. UIDeviceOrientation typedef NS_ENUM(NSInteger, UIDeviceOrientation) { UIDeviceOrientationUnknown, UIDeviceOrientationPortrait, // Device oriented vertically, home button on the bottom UIDeviceOrientationPortraitUpsideDown, // Device oriented vertically, home button on the top UIDeviceOrientationLandscapeLeft, // Device oriented horizontally, home button on the right UIDeviceOrientationLandscapeRight, // Device oriented horizontally, home button on the left UIDeviceOrientationFaceUp, // Device oriented flat, face up UIDeviceOrientationFaceDown // Device oriented flat, face down };
  • 18. 能够发布通知的⼀一些类 • 注意消息后⾯面的冒号是⽅方法名称的⼀一部分 - orientationChanged: • 可以发布通知的⼀一些类: • UIApplication • NSManagedObjectContext • MPMoviePlayerController • NSFileHandle • UIWindow • UITextField • UITextView
  • 20. • 很多应⽤用程序在⽤用户旋转设备的时候会把所有的 视图旋转并调整⼤大⼩小 • 我们可以使⽤用 UIDevice notification 来实现这个, 但这会是⼀一个很⼤大量的⼯工作。幸运的是,我们可 以使⽤用 autorotation 来简化这个过程
  • 21. • 如果屏幕上的视图通过⼀一个 view controller 被控 制,当设备被翻转时,这个 view controller 会被询 问是否可以翻转 view 。如果 view controller 同意 的话,view 被调整⼤大⼩小并且翻转。所有的 subviews 也被调整⼤大⼩小和翻转
  • 22. HeavyViewController • 我们实现⼀一个 UIViewController 的⼦子类来获得⾃自动 翻转特性。这个 view controller 的 view 会拥有 subviews,所以我们使⽤用带 XIB ⽂文件的 UIViewController 模版来创建这个类 • 选择 File -> New -> File..., 从 iOS 部分,选择 Cocoa Touch, 选择 Objective-C 类模版 • 命名⼦子类为 HeavyViewController, 选择 UIViewController 作为超类,勾选 “With XIB for user interface”
  • 23. 实现 autorotation • 这样我们就有了⼀一个名为 HeavyViewController 的 UIViewController ⼦子类 • 同时也有了⼀一个名为 HeavyViewController.xib 的 XIB ⽂文件 • 这个 XIB ⽂文件有⼀一个类型是 HeavyViewController 的 File’s Owner, 它的 view outlet 被连接到了⼀一个 320x460(548)点⼤大⼩小的 view 对象
  • 24. • 要在 HeavyRotation 中实现 autorotation,我们需 要做下⾯面两个⼯工作: • 在 HeavyViewController 中重写 shouldAutorotateToInterfaceOrientation: 以允许 autorotation • 针对每个 subview ⼩小⼼心的设置 autoresize mask 以在 superview 被调整到填充被翻转的窗⼝口时表现合理
  • 25. 设备翻转:iPhone 和 iPad • 当设备翻转时,当前显⽰示在屏幕上的 view 的 view controller 将被发送⼀一个 shouldAutorotationToInterfaceOrientation: 消息。这 个⽅方法返回⼀一个 BOOL 来标明是否可以翻转这个 view controller 的 view
  • 26. 设备翻转:iPhone 和 iPad • 对于 iPhone 应⽤用⽽而⾔言,我们⼀一般允许 right-side up(正⽴立), landscape left(平放左边在上), 和 landscape right(平放右边在上);在 iPad 上,⼀一 般允许全部⽅方向,包括 upside-down(倒⽴立) • 我们在 HeavyViewController.m 中,为两种常⻅见的 iPhone 朝向返回 YES - (BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)toInterfaceOrientation { return (toInterfaceOrientation == UIInterfaceOrientationPortrait) || UIInterfaceOrientationIsLandscape(toInterfaceOrientation); }
  • 27. HeavyViewController XIB 布局 • 增加⼀一些内容来翻转 • 拖⼀一张图⽚片到 project navigator 中 • 打开 HeavyViewController.xi b, 在 view 上放⼀一个 slider,⼀一个 image view,两个 button
  • 28. UIImageView 属性 • 设置 UIImageView 的 属性为刚才的图⽚片⽂文 件,设置 Mode 为 Aspect Fit,设置背景颜 ⾊色为 Light Gray
  • 29. autoresizing mask • 当设备翻转时,⾸首先 view 被翻转到和设备的朝向 对⻬齐;其次 view 的⼤大⼩小被调整到适合屏幕 • 在 portrait 模式下的 320 宽和 480 ⾼高的 view 将变 成 480 宽和 320 ⾼高的 landscape 模式 • 当 view 被调整⼤大⼩小时,它将 autoresize 它的所有 subview • 每个 subview 被根据它的 autosizing mask 属性进 ⾏行调整 • 可以通过在 XIB ⽂文件中选择⼀一个 view,然后在 size inspector 中编辑 autoresizing mask
  • 30. Autoresizing 设置 • image view 应该保持在中间位置 • 滑块应该变宽,和 superview 的顶部保持固定距 离,并且和左右边界保持同样距离 • 两个按钮应该停留在它们相应的 corner 并且不⾃自 动调整⼤大⼩小
  • 31. 设成 rootViewController • 创建⼀一个 HeavyViewController 的实例,并且把它 设置成 window 的 rootViewController - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; // Override point for customization after application launch. UIDevice *device = [UIDevice currentDevice]; [device beginGeneratingDeviceOrientationNotifications]; NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; [nc addObserver:self selector:@selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:device]; HeavyViewController *hvc = [[HeavyViewController alloc] init]; [[self window] setRootViewController:hvc]; self.window.backgroundColor = [UIColor whiteColor]; [self.window makeKeyAndVisible]; return YES; }