• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
08 Notification and Rotation
 

08 Notification and Rotation

on

  • 484 views

iOS 通知和翻转,观察者模式, 通知中心, UIDevice 通知

iOS 通知和翻转,观察者模式, 通知中心, UIDevice 通知

Statistics

Views

Total Views
484
Views on SlideShare
484
Embed Views
0

Actions

Likes
0
Downloads
4
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    08 Notification and Rotation 08 Notification and Rotation Presentation Transcript

    • 通知和翻转范圣刚,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]); }
    • UIDeviceOrientationtypedef 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, facedown};
    • 能够发布通知的⼀一些类• 注意消息后⾯面的冒号是⽅方法名称的⼀一部分 -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 *)applicationdidFinishLaunchingWithOptions:(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;}