iOS开发笔记之四十七——多线程场景下的KVO使用参考方案
来源:互联网 发布:资产抵押债券知乎 编辑:程序博客网 时间:2024/05/20 09:45
如果你取检索网络资料会发现,有人直接不建议把KVO与多线程混合使用,因为KVO的响应和KVO观察的值变化是在一个线程上的,不同的线程可能会导致不可预知的后果。参考资料见这里:
(1)http://objccn.io/issue-7-3/
(2)http://blog.csdn.net/hello_hwc/article/details/43815743
当然,场景总是千变万化的,下面我就介绍一种多线程下使用KVO的场景。
具体场景如下:
(1)主线程里面请求数据,数据是一个类似http://www.dpfile.com/sc/appskin/20160309163700.zip的链接;
(2)数据拿到后,建立一个子线程,线程去请求zip包数据,并解压缩到本地(图片.png文件);
(3)通知(KVO)主线程,去本地目录取图片资源,刷新UI;
具体代码实现如下
1、方案一:
(1)主线程viewDidLoad方法中,注册监听,并发送数据请求;
@weakify(self) [RACObserve(self, enablePromotionSkin)subscribeNext:^(NSNumber *enablePromotionSkin) { @strongify(self); if ([[self enablePromotionSkin] integerValue]) { //...刷新UI } }];
(2)子线程中,解压缩并通知主线程刷新UI;
- (RACSignal *)fetchSkinSignalWithConfig:(NVModelBaseOSAppPromoDo *)skinConfig { return (RACSignal *)createSignal:(RACDisposable * (^)(id<RACSubscriber> subscriber))didSubscribe { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ //下载、解压缩操作 //... //md5校验 if ([[responseData md5] isEqualToString:skinConfig.md5]) { self.enablePromotionSkin = @(YES); //通知主线程 } }); }]; }
这样的调用KVO是直接跨越线程,实际运行时发现,最终从主线程发送请求,到图片刷出来,会经历5-10s的时间,zip包没有超过500k,并且wifi网络下,这个真的好慢,没有人能容忍。
KVO消息从子线程发出,到主线程上响应,而nonatomic属性的enablePromotionSkin是非线程安全的,这样设计会导致不可预知的问题。
2、方案二:
RAC本身有比较强大机制可以处理这种异步场景:
(1)主线程注册时,强制指定了主线程处理消息;
@weakify(self) [[RACObserve(self, enablePromotionSkin) deliverOn:[RACScheduler mainThreadScheduler]] subscribeNext:^(NSNumber *enablePromotionSkin) { @strongify(self); if ([self enablePromotionSkin] integerValue) { //...刷新UI } }];(2)子线程处理时,强制由主线程处理;
- (RACSignal *)fetchSkinSignalWithConfig:(NVModelBaseOSAppPromoDo *)skinConfig{ return [RACSignal startEagerlyWithScheduler:[RACScheduler mainThreadScheduler] block:^(id<RACSubscriber> subscriber) { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ //.... }); }];}这样之后,图片的下载一般会在2s左右就会刷新出来,基本达到了预期效果;
3、方案三:
如果不用RAC提供的机制,我们也可以采取直接主线程发消息的方法:
dispatch_async(dispatch_get_main_queue(), ^{ self.enablePromotionSkin = YES; });
这种方法可以达到与方案二相同的效果。
0 0
- iOS开发笔记之四十七——多线程场景下的KVO使用参考方案
- iOS开发笔记之四十三——日历NSCaledar使用过程中遇到的一个苹果系统bug
- iOS开发笔记之四十——一个诡异的编译报错问题
- [ios开发基础之]KVO的使用
- IOS开发之----KVO的使用
- Android开发笔记(四十七)Runnable接口实现多线程
- 【iOS】KVC 和 KVO 的使用场景
- 【iOS】KVC 和 KVO 的使用场景
- 【iOS】KVC 和 KVO 的使用场景
- 【iOS】KVC 和 KVO 的使用场景
- 【iOS】KVC 和 KVO 的使用场景
- 【iOS】KVC 和 KVO 的使用场景
- iOS开发笔记之七——应用的生命周期
- iOS开发笔记之基于键值的观察者模式(KVO)
- iOS开发笔记之十四——Xcode 6.0.1下出现Thread 1: signal SIGPIPE问题的参考解决方案
- iOS开发—iOS多线程编程之NSThread的使用
- iOS高级编程之KVO、KVC的理解与使用场景
- iOS 开发之KVO的底层实现
- egret第一步
- Excel数据大量导入MySQL--MySQL数据换行符回车符替换处理
- markdown语法整理
- 如何查看真机的沙盒(图文教程)
- eclipse无法启动的各种解决方法
- iOS开发笔记之四十七——多线程场景下的KVO使用参考方案
- C++之include<iostream>与include<iostream.h>
- 分类添加属性,运行时添加对象属性和基本类型属性
- 浏览器~加载,解析,渲染
- 二分查找法
- Java并发编程:Condition实现线程间协作
- WordPress SEO ☞ WordPress网站终极优化指南
- Android学习----自适应国际化语言
- 高通QCOM 8610平台电量计算