NSNotification,NSNotificationCenter的使用、iOS中五种对象间传值的方式
学习内容
欢迎关注我的iOS学习总结——每天学一点iOS:https://github.com/practiceqian/one-day-one-iOS-summary
NSNitification与NotificationCenter(通知与通知中心)
通知的使用
[[NSNotificationCenter defaultCenter]addObserver:selfselector:@selector
(noticeAction:) name:@"name" object:nil];
注册观察者
NSNotification* notice = [NSNotification notificationWithName:@"name" object:nil userInfo:params];
[[NSNotificationCenter defaultCenter]postNotification:notice];
创建一个通知并发送
观察者对象的注册一定要比通知的发送提前,否则的话会接收不到通知
通知和delegate的基本区别
- 通知是允许多对多的,而delegate只能是一对一的
- 通知的耦合度较低,发送方不需要知道通知方的任何情况,而delegate不行
- 通知的效率比起delegate略差
通知是同步还是异步的?
- postNotification:通知的发送总是会卡住当前线程,等待所有的observer对象执行(如果没有经过特殊处理,接收者对象的selector与postNotification在同一线程执行)完成后才会继续往下执行,所以是同步的
通知的移除
- 在iOS9之前的版本中,如果对一个观察者对象在delloc之前之中没有从通知中心移除(remove)的话,会产生BAD_ACCESS野指针错误,导致crash
- iOS9.0及以后的版本中不会造成crash
- 原因:iOS9.0之前NSNotificationCenter持有的是observer的unsafe_uncertain指针,如果观察者对象已经被释放,但是没有从通知中心移除,那么postNotification方法会向观察者已经被回收的内存发送消息,就会造成野指针访问错误,iOS9.0以后,系统将unsafe_uncertain指针更改成了weak指针(对象回收,自动置nil),向nil发送消息不会差生任何问题(同时这里说明了oc是可以向nil发送消息的)
异步通知
[[NSNotificationQueue defaultQueue]enqueueNotification:notice postingStyle:NSPostASAP];
----------------------------------------------------------------------------------typedef NS_ENUM(NSUInteger, NSPostingStyle) {
//空闲发送通知 当运行循环处于等待或空闲状态时,发送通知,对于不重要的通知可以使用。
NSPostWhenIdle = 1,
//尽快发送通知 当前运行循环迭代完成时,通知将会被发送,有点类似没有延迟的定时器。
NSPostASAP = 2,
//和postNotification一样是同步通知
NSPostNow = 3
};
三种枚举类型代表三种发送方式(异步/同步都可)
同样的,异步发送通知的话还可以使用开启一个新的线程的方式
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[[NSNotificationCenter defaultCenter]postNotification:notice];
});
通知的合并(待完善)
[[NSNotificationQueue defaultQueue] enqueueNotification:notice postingStyle:NSPostASAP coalesceMask:NSNotificationNoCoalescing forModes:nil];
-----------------------------------------------------------------------------------
typedef NS_OPTIONS(NSUInteger, NSNotificationCoalescing) {
// 不合成
NSNotificationNoCoalescing = 0,
// 根据NSNotification的name字段进行合成
NSNotificationCoalescingOnName = 1,
// 根据NSNotification的object字段进行合成
NSNotificationCoalescingOnSender = 2
};
NSNotificationQueue除了有异步通知的能力之外,也能对当前队列的通知根据NSNotificationCoalescing类型进行合并,需要配合不同的NSRunLoopMode来进行
通过合并通知我们可以用来保证相同的通知只被发送一次
NSNotificationCenter实现原理
- 通知中心用来管理通知的接收和发送,一开始将观察者注册到通知中心的通知调度表中,然后发送通知时利用标识符name和object识别出观察者,并调用相应的观察者方法,即传递消息(消息传递机制),如果是基于block创建的通知就调用NSNitification的block
NSNotificationCenter使用block方式添加的观察者
- (id<NSObject>)addObserverForName:(NSString *)name
object:(id)obj
queue:(NSOperationQueue *)queue
usingBlock:(void (^)(NSNotification *note))blockaddObserver使用一个现存的对象作为观察者(一般为self),而使用block方法会创建一个匿名的(id)对象作为观察者,这个匿名对象会在指定的队列上去执行block
如果
queue为nil,则消息是默认在post线程中同步处理,即通知的post与转发是在同一线程中,不为nil的话就会在我们指定的队列中执行如果一个给定的通知触发了多个观察者的
block操作,则这些操作会在各自的Operation Queue中被并发执行。所以我们不能去假设操作的执行会按照添加观察者的顺序来执行这个方法会返回一个匿名的观察者对象,我们需要手动释放这个对象。
iOS中对象间的五种传值方式(属性、代理、单例、Block、通知)
属性传值
- 通过对象的公有属性进行传值
代理传值
在委托方定义协议,协议中声明@required/@optional方法,声明一个代理属性,使用weak修饰符
在代理方遵守协议,实现协议中的方法
初始化委托对象,将委托对象的代理设置为self(代理对象自身)
查看代理方是否实现了需要执行的选择子(SEL),如果实现了便开始执行
if ([self.delegate respondsToSelector:@selector(codeIOS)]) {
// 让代理方执行协议中的方法
[self.delegate SEL];
}
代理传值一般用于逆向传值,如:A控制器跳转到B控制器,B控制器为委托对象,A控制器为代理对象,B对象的代理为A对象,那么在B对象中可以传值给A对象,并在A对象中执行相应的方法
单例模式传值
- 将一个类写成单例(常用dispatch_once),这样这个类就只含有全局唯一的实例,可以向整个程序提供实例
- 如果一个类创建实例会耗费很多资源,那么可以将这个类写成单例类,节省alloc,init的时间
- 在程序中如果多个类访问同一个变量,那么也可以将将该变量写入单例类中,调用起来更加方便
使用block代码块进行传值
可以用于数据在多个对象间传递,网络请求的回调等
//在对象B中block作为方法参数
- (void)getNextPage:(void (^)(BOOL))completeBlock{
//block可以嵌套,第一层block可以在最后的block体中进行回调
[self getPage:self.page complete:^(NSMutableArray *result) {
if ([result count]) {
self.page++;
[self.musicList addObjectsFromArray:result];
if (completeBlock) {
//需要回调时,执行block
completeBlock(true);
}
}else{
if (completeBlock) {
completeBlock(false);
}
}
}];
}
------------------------------------------------------------------------------
//在对象A中isSucceed为回调回来的值
[strongSelf.musicModel getNextPage:^(BOOL isSucceed) {
if (isSucceed) {
[strongSelf.waterFallCollectionView reloadData];
}
}];
通知传值
- NSNotification的使用就是通知传值的一些用法
NSNotification,NSNotificationCenter的使用、iOS中五种对象间传值的方式的更多相关文章
- iOS中几种常用的数据存储方式
自己稍微总结了一下下,方便大家查看 1.write直接写入文件的方法 永久保存在磁盘中,可以存储的对象有NSString.NSArray.NSDictionary.NSData.NSNumber,数据 ...
- iOS中4种判断网络请求的方式(系统状态栏、AFNetworking、Reachability、自定义)
iOS 实时判断网络状态 方法一:利用系统状态栏判断网络状态 // 状态栏是由当前app控制的,首先获取当前app UIApplication *app = [UIApplication shared ...
- iOS页面间传值的方式(NSUserDefault/Delegate/NSNotification/Block/单例)
iOS页面间传值的方式(NSUserDefault/Delegate/NSNotification/Block/单例) 实现了以下iOS页面间传值:1.委托delegate方式:2.通知notific ...
- 【转】iOS页面间传值的方式(Delegate/NSNotification/Block/NSUserDefault/单例)-- 不错
原文网址:http://www.cnblogs.com/JuneWang/p/3850859.html iOS页面间传值的方式(NSUserDefault/Delegate/NSNotificatio ...
- iOS页面间传值的方式 (Delegate/NSNotification/Block/NSUserDefault/单例)
iOS页面间传值的方式(Delegate/NSNotification/Block/NSUserDefault/单例) iOS页面间传值的方式(NSUserDefault/Delegate/NSN ...
- Android中三种超实用的滑屏方式汇总(转载)
Android中三种超实用的滑屏方式汇总 现如今主流的Android应用中,都少不了左右滑动滚屏这项功能,(貌似现在好多人使用智能机都习惯性的有事没事的左右滑屏,也不知道在干什么...嘿嘿),由于 ...
- Android中四种补间动画的使用示例(附代码下载)
场景 Android中四种补间动画. 透明度渐变动画 旋转动画 缩放动画 平移动画 注: 博客: https://blog.csdn.net/badao_liumang_qizhi关注公众号 霸道的程 ...
- JavaScript中四种不同的属性检测方式比较
JavaScript中四种不同的属性检测方式比较 1. 用in方法 var o = {x:1}; "x" in o; //true "y" in o; //fa ...
- 关于iOS中几种第三方对XML/JSON数据解析的使用
Json XML 大数据时代,我们需要从网络中获取海量的新鲜的各种信息,就不免要跟着两个家伙打交道,这是两种结构化的数据交换格式.一般来讲,我们会从网络获取XML或者Json格式的数据,这些数据有着特 ...
随机推荐
- synchronized 与 volatile 区别 还有 volatile 的含义
熟悉并发的同学一定知道在java中处理并发主要有两种方式: 1,synchronized关键字,这个大家应当都各种面试和笔试中经常遇到. 2,volatile修饰符的使用,相信这个修饰符大家平时在项目 ...
- CVE-2019-0232 远程代码执行漏洞-复现
0x00 漏洞介绍 该漏洞是由于Tomcat CGI将命令行参数传递给Windows程序的方式存在错误,使得CGIServlet被命令注入影响. 该漏洞只影响Windows平台,要求启用了CGISer ...
- MAC 上brew 更新 出错
在MAC上brew update的时候出现报错:Error: /usr/local must be writable! 错误,在该文章中也给出解决办法(sudo chown -R $(whoami) ...
- Delphi学习手记——单引号和双引号的区别
单引号和双引号的区别 双引号表示其中字符可能包含变量,而单引号表示整个引号内的东西都当成字符串来处理. 也就是说:没有内设变量就用单引号'',有就用双引号"". 举例说明: $va ...
- 微信小程序 —搜索框
wxSearch优雅的微信小程序搜索框 一.功能 支持自定义热门key 支持搜索历史 支持搜索建议 支持搜索历史(记录)缓存 二.使用 1.将wxSearch文件夹整个拷贝到根目录下 2.引入 // ...
- 详解 JDK8 新增的日期时间类
JDK8 新增的日期时间类 在本人之前的博文<处理时间的类 -- System类.Date类 .SimpleDateFormat类 与 Calendar类>中,讲到过表示时间的类,有三类: ...
- 虎符ctf-MISC-奇怪的组织(看完官方题解,找到了)
一道取证题,一整场比赛,基本就死磕了这一题 写的很乱,因为当时的思维就是那么乱,完全没有注意到出题人的提示, 还没做出来,没有找到关键key 那个人的real name 文档:虎符.note链接:ht ...
- 实例讲解Springboot以Template方式整合Redis及序列化问题
1 简介 之前讲过如何通过Docker安装Redis,也讲了Springboot以Repository方式整合Redis,建议阅读后再看本文效果更佳: (1) Docker安装Redis并介绍漂亮的可 ...
- python os模块判断文件是否存在
import os os.path.exists(test_file.txt)
- SK-learn实现k近邻算法【准确率随k值的变化】-------莺尾花种类预测
代码详解: from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split fr ...