「这是我参与2022首次更文挑战的第41天,活动详情查看:2022首次更文挑战」。
前言
- 通知的发布
- 通知的监听
- 通知的移除
本地通知和代理的选择:
- 共同点:都能饿按此对象间的通信
- 不同点:代理是一对一关系;通知是多对多的关系(1个对象能告诉N个对象发生了什么事情,1个对象能得知N个对象发生了什么事情)
I 本地通知的使用
1.1 通知中心(NSNotificationCenter)
每个应用程序都有一个通知中心:专门负责协助不同对象间的消息通信 1.任何一个对象都可以向通知中心发布通知(NSNotification),来描述自己在做什么事情。 其他感兴趣的监听器(Observer)可以申请在某个特定通知发布时(或者某个特定的对象发布通知时),收到这个通知。
1.2 通知对象(NSNotification)
- 一个完整的通知通常包含三个属性:通知名称name、通知的发布者、一些额外的信息UserInfo
- 初始化一个通知对象
- 发布通知(通知中心NSNotificationCenter 提供了相应的方法来帮助发布通知)
1.3 注册通知监听器
NSNotificationCenter 提供了相应方法来注册一个监听通知的监听器(observer)
- (void)addObserver:(id)observer selector:(SEL)aSelector name:(NSString *)aName object:(id)anObject;
/**
observer:监听器,即谁要接收这个通知;
aSelector:收到通知后,回调监听器的这个方法,并且把通知对象当做参数传入;
aName:通知的名称。如果为nil,那么无论通知的名称是什么,监听器都能收到这个通知;
anObject:通知的发布者。如果为anObject和aName都为nil,监听器都收到所有的通知
- (id)addObserverForName:(NSString*)name object:(id)obj queue:(NSOperationQueue *)queue usingBlock:(void (^)(NSNotification* note))block;
/**
name:通知的名称;
obj:通知发布者;
block:收到对应的通知时,会回调这个block;
queue:决定了block在哪个操作队列中执行,如果传nil,默认在当前操作队列中同步执行;
1.4 取消注册通知监听器
通知中心不会retain监听器对象,在通知中心注册过的对象,必须在该对象释放前取消注册;否则,当相应的通知再次出现时,通知中心仍然会向该监听器发送消息,可能会导致应用的崩溃。--- 尤其再iOS8,7 系统经常发生
NSNotificationCenter 提供了相应的方法来取消注册observer。
- (void)removeObserver:(id)observer;
- (void)removeObserver:(id)observer name:(NSString *)aName object:(id)anObject;
//一般在监听器销毁之前取消注册(如在监听器中加入下列代码):
- (void)dealloc
{
//[super dealloc]; 非ARC中需要调用此句
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
1.5 键盘通知
我们经常需要在键盘弹出或者隐藏的时候做一些特定的操作,因此需要监听键盘的状态
- 键盘状态改变的时候,系统会发出一些特色的通知
//1. 注册Observer
[center addObserver:self selector:@selector(keyboardWillChangeFrame:) name:UIKeyboardWillChangeFrameNotification object:nil];
- 系统发出键盘通知的时候,会附带一下跟键盘有关的额外字典信息
- 通知处理示例
/**
处理键盘通知
处理好view的frame和键盘frame的关系--移动view
*/
- (void)keyboardWillChangeFrame: (NSNotification *) notification{
NSLog(@"%@",notification.userInfo);
//修改UIWindow的背景颜色
// UIWindow *keyWindow =[UIApplication sharedApplication].keyWindow;
[self.view.window setBackgroundColor:self.tableView.backgroundColor];
//键盘的弹出完成时的frame UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 227}, {320, 253}}";
//键盘隐藏结束之后的frame UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 480}, {320, 253}}";
CGRect keyBoardFrame = [notification.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
//2.动画平移view控件
// UIKeyboardAnimationDurationUserInfoKey = "0.25";
//1>获取动画的持续时间
CGFloat keyBoardAnimationDuration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] floatValue];
//2>计算平移的y值
CGFloat keyBoardY = keyBoardFrame.origin.y ;//键盘的实时y值
CGFloat y = keyBoardY- KScreenHeight;//平移的y值
[UIView animateWithDuration:keyBoardAnimationDuration animations:^{
[self.view setTransform:CGAffineTransformMakeTranslation(0, y)];//设置平移的x、y值
}];
}
#pragma mark - scrollView 的代理方法
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
NSLog(@"%s",__func__);
//关闭键盘,此时view的frame要还原
[self.view endEditing:YES];
}
II block的使用
2.1 使用typeblock实现消息的传递
/** 使用typeblock实现消息的传递*/
typedef void(^HSHeaderViewBlockForClick)(id);//定义block,常常使用copy
@property (nonatomic,copy) HSHeaderViewBlockForClick block;//属性定义
/** 执行自己的block*/
#pragma mark - titleButtonViewClick事件的处理
/**
合并cell,展开cell的触发处理
*/
- (void) titleButtonViewClick: (HSHeaderView *) headerView{
//当分组的cell个数为0 的时候,即使合上,设置一个展开、合上标志属性,以便进行操作方法:(CGFloat) tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
[self.friendsGroup setIsOpen:!self.friendsGroup.isOpen];
//方式一、通知代理
// //先判断代理对象是否实现了代理方法
// if ([self.delegate respondsToSelector:@selector(headerViewForclick:)]) {
// [self.delegate headerViewForclick:self];
// }
//方式二、block
if (self.block) {
self.block(self);//执行block
}
}
2.2 例子
#pragma mark -
#if 1
/**
自定义UITableViewHeaderFooterView
关于控件没显示的经验小结:
1》父控件的frame
2》当前控件的frame
3》当前控件的hidden属性
4》当前控件的alpha<= 0.01
*/
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
HSFriendsGroup *friendsGroupModel = self.fridendsGroupArray[section];
HSHeaderView *headerView = [HSHeaderView tableHeaderViewWithFriendsGroup:friendsGroupModel TableView:tableView];
//设置代理对象
// [HeaderView setDelegate:self];
//设置block,定义具体实现
[headerView setBlock:^(HSHeaderView * view ){
//刷新分组数据
NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:section];
[tableView reloadSections:indexSet withRowAnimation:UITableViewRowAnimationAutomatic];
}];
[headerView setSection:section];
return headerView;
}
#endif
see also
案例:QQ聊天界面&QQ好友列表:kunnan.blog.csdn.net/article/det…