文章目录
  1. 1. 代理
  2. 2. 代理和通知的区别
  3. 3. KVC\KVO
  4. 4. UIDevice通知
  5. 5. 键盘通知
  6. 6. 通知和代理的选择
  7. 7. 实例
    1. 7.1. 使用步骤
  8. 8. 举个栗子
    1. 8.1. 键盘通知
    2. 8.2. 方法里面拿到键盘高度
  9. 9. 参考

代理

  • 代理设计模式的作用:

    • 1.A对象监听B对象的一些行为,A成为B的代理
    • 2.B对象想告诉A对象一些事情,A成为B的代理
  • 代理设计模式的总结:

    • 如果你想监听别人的一些行为,那么你就要成为别人的代理
    • 如果你想告诉别人一些事情,那么就让别人成为你的代理
  • 代理设计模式的开发步骤

    • 1.拟一份协议(协议名字的格式:控件名 + Delegate),在协议里面声明一些代理方法(一般代理方法都是@optional)
    • 2.声明一个代理属性:@property (nonatomic, weak) id<代理协议> delegate;
    • 3.在内部发生某些行为时,调用代理对应的代理方法,通知代理内部发生什么事
    • 4.设置代理:xxx.delegate = yyy;
    • 5.yyy对象遵守协议,实现代理方法

代理和通知的区别

  • 代理:1个对象只能告诉另1个对象发生了什么事
  • 通知:1个对象可以告诉N个对象发生了什么事

KVC\KVO

  • KVC(Key Value Coding)常见作用:给模型属性赋值
  • KVO(Key Value Observing)常用作用:监听模型属性值的改变
  • KVO的使用步骤
1
2
3
4
5
6
7
8
9
10
11
// cc监听了aa的name属性的改变
[aa addObserver:cc forKeyPath:@"name" options: NSKeyValueObservingOptionOld context:nil];

// cc得实现监听方法
/**
* 当监听到object的keyPath属性发生了改变
*/
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
NSLog(@"监听到%@对象的%@属性发生了改变, %@", object, keyPath, change);
}

UIDevice通知

UIDevice类提供了一个单粒对象,它代表着设备,通过它可以获得一些设备相关的信息,比如电池电量值(batteryLevel)、电池状态(batteryState)、设备的类型(model,比如iPod、iPhone等)、设备的系统(systemVersion)


过[UIDevice currentDevice]可以获取这个单例对象

1
2
3
4
5
UIDevice对象会不间断地发布一些通知,下列是UIDevice对象所发布通知的名称常量:
UIDeviceOrientationDidChangeNotification // 设备旋转
UIDeviceBatteryStateDidChangeNotification // 电池状态改变
UIDeviceBatteryLevelDidChangeNotification // 电池电量改变
UIDeviceProximityStateDidChangeNotification // 近距离传感器(比如设备贴近了使用者的脸部)

键盘通知

我们经常需要在键盘弹出或者隐藏的时候做一些特定的操作,因此需要监听键盘的状态

1
2
3
4
5
6
7
键盘状态改变的时候,系统会发出一些特定的通知
UIKeyboardWillShowNotification // 键盘即将显示
UIKeyboardDidShowNotification // 键盘显示完毕
UIKeyboardWillHideNotification // 键盘即将隐藏
UIKeyboardDidHideNotification // 键盘隐藏完毕
UIKeyboardWillChangeFrameNotification // 键盘的位置尺寸即将发生改变
UIKeyboardDidChangeFrameNotification // 键盘的位置尺寸改变完毕
1
2
3
4
5
系统发出键盘通知时,会附带一下跟键盘有关的额外信息(字典),字典常见的key如下:
UIKeyboardFrameBeginUserInfoKey // 键盘刚开始的frame
UIKeyboardFrameEndUserInfoKey // 键盘最终的frame(动画执行完毕后)
UIKeyboardAnimationDurationUserInfoKey // 键盘动画的时间
UIKeyboardAnimationCurveUserInfoKey // 键盘动画的执行节奏(快慢)

通知和代理的选择

共同点

利用通知和代理都能完成对象之间的通信
(比如A对象告诉D对象发生了什么事情, A对象传递数据给D对象)

不同点

代理 : 1个对象只能告诉另1个对象发生了什么事情
通知 : 1个对象能告诉N个对象发生了什么事情, 1个对象能得知N个对象发生了什么事情

实例

使用步骤

  1. 观察者注册消息通知
    1
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(getUserProfileSuccess:) name:@"Notification_GetUserProfileSuccess" object:nil];

notificationObserver 观察者 : self
notificationSelector 处理消息的方法名: getUserProfileSuccess
notificationName 消息通知的名字: Notification_GetUserProfileSuccess
notificationSender 消息发送者 : 表示接收哪个发送者的通知,如果第四个参数为nil,接收所有发送者的通知

  1. 发送消息通知
1
2
3
4
//UserProfile Is A Model
//@interface UserProfile : NSObject

[[NSNotificationCenter defaultCenter] postNotificationName:@"Notification_GetUserProfileSuccess" object:userProfile userInfo:nil];

notificationName 消息通知的名字: Notification_GetUserProfileSuccess

notificationSender 消息发送者: userProfile

  1. 观察者处理消息
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14

    - (void) getUserProfileSuccess: (NSNotification*) aNotification
    {
    self.userProfile = [aNotification object];

    lblName.text = self.userProfile.Name;
    lblEENO.text = self.userProfile.EENO;
    lblNric.text = self.userProfile.NRIC;
    lblBirthday.text =self.userProfile.Birthday;
    lblHireDate.text = self.userProfile.Hiredate;

    txtMobilePhone.text = self.userProfile.Mobile;
    txtEmail.text = self.userProfile.Email;
    }

NSNotification 接受到的消息信息,主要含:
Name: 消息名称 Notification_GetUserProfileSuccess
object: 消息发送者 userProfile
userInfo: 消息传递的数据信息

  1. 观察者注销,移除消息观察者

虽然在 IOS 用上 ARC 后,不显示移除 NSNotification Observer 也不会出错,但是这是一个很不好的习惯,不利于性能和内存。

注销观察者有2个方法:

a. 最优的方法,在 UIViewController.m 中:

1
2
3
-(void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}

If you see the method you don’t need to call [super dealloc]; here, only the method without super dealloc needed.

b. 单个移除:

1
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"Notification_GetUserProfileSuccess" object:nil];

举个栗子

获取键盘高度

1
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onKeyboardNotification:) name:UIKeyboardWillChangeFrameNotification object:nil];

这个方法可以检测输入面板切换时候的通知,更加有效

1
2
3
4
- (void)onKeyboardNotification:(NSNotification *)notification {
CGRect keyboardFrame = ((NSValue *) notification.userInfo[UIKeyboardFrameEndUserInfoKey]).CGRectValue;

}

键盘通知

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
- (void)viewWillAppear:(BOOL)animated{
//设置状态栏白色
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleDefault animated:NO];
[self.textField becomeFirstResponder];
self.textField.text = @"" ;
//注册键盘将要弹出的提醒
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardShow:) name:UIKeyboardWillShowNotification object:nil];
//注册键盘将要消失时的提醒
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardHide:) name:UIKeyboardWillHideNotification object:nil];
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
//移除一切编辑状态
[self.view endEditing:YES];
//移除注册的键盘将要显示的通知
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
// //移除注册的键盘将要隐藏的通知
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
_tableView.frame = CGRectMake(0, 64, ScreenWidth, ScreenHeight - 64);
}

方法里面拿到键盘高度

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- (void)keyboardShow:(NSNotification *)notification {
NSDictionary * info = [notification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
NSLog(@"%f__________", kbSize.height);
_tableView.frame = CGRectMake(0, 64, ScreenWidth, ScreenHeight - 64 - kbSize.height);

//也可以使用UIView动画

}
- (void)keyboardHide:(NSNotification *)notification {
// NSDictionary * info = [notification userInfo];
// CGSize kbSize = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
// NSLog(@"%f__________", kbSize.height);
_tableView.frame = CGRectMake(0, 64, ScreenWidth, ScreenHeight - 64);
}

参考

文章目录
  1. 1. 代理
  2. 2. 代理和通知的区别
  3. 3. KVC\KVO
  4. 4. UIDevice通知
  5. 5. 键盘通知
  6. 6. 通知和代理的选择
  7. 7. 实例
    1. 7.1. 使用步骤
  8. 8. 举个栗子
    1. 8.1. 键盘通知
    2. 8.2. 方法里面拿到键盘高度
  9. 9. 参考