iOS 编写高质量Objective-C代码(七)
栏目: Objective-C · 发布时间: 6年前
内容简介:级别: ★★☆☆☆标签:「iOS」「GCD」「Objective-C」作者:MrLiuQ
级别: ★★☆☆☆
标签:「iOS」「GCD」「Objective-C」
作者:MrLiuQ
审校:QiShare团队
前言:
这几篇文章是小编在钻研《Effective Objective-C 2.0》的知识产出,其中包含作者和小编的观点,以及小编整理的一些demo。希望能帮助大家以简洁的文字快速领悟原作者的精华。
在这里,QiShare团队向原作者Matt Galloway表达诚挚的敬意。
文章目录如下:
iOS 编写高质量Objective-C代码(七)本篇的主题是iOS中的 “ 大中枢开发 GCD ” 。
先简单介绍一下今天的主角: GCD
。
- GCD(
Grand Central Dispatch
):一种与块相关的技术,提供了对线程的抽象管理(基于派发队列dispatch queue
)。GCD会根据系统资源情况,适时且高效地 “创建线程” 、“复用线程” 、 “销毁线程” 。
一、多用派发队列,少用同步锁
问:在iOS开发中,如何通过锁来提供同步机制?(以前面试中,经常问道的问题..)
答:在GCD出现之前,有两种方式:
- 同步块:
@synchronized(self) {...}
- (void)synchronizedMethod { @synchronized (self) { // Safe area... } } 复制代码
- NSLock:
[_lock lock];
&[_lock unlock];
_lock = [[NSLock alloc] init]; - (void)synchronizedMethod { [_lock lock]; // Safe area.. [_lock unlock]; } 复制代码
不过这两种写法效率很低,如果有很多属性,那么每个属性的同步块都要等其他同步块执行完毕才能执行。
GCD出现后,GCD与Block相结合,使开发变得更加简单、高效。
问:如何保证属性读写时线程绝对安全? 答:在属性写入时,使用栅栏块 barrier
。只有当前所有并发块都执行完毕后,才会执行 barrier
块,然后才会继续向下处理。
- 思路如下:
- 代码如下:
_syncQueue = dispatch_queue_create("syncQueue", DISPATCH_QUEUE_CONCURRENT); //! 读取字符串 - (NSString *)someString { __block NSString *localSomeString; dispatch_sync(_syncQueue, ^{ localSomeString = _someString; }); return localSomeString; } - (void)setSomeString:(NSString *)someString { dispatch_barrier_async(_syncQueue, ^{ _someString = someString; }); } 复制代码
二、多用GCD,少用performSelector系列方法
performSelector
系列方法的缺点有两个:
-
performSelector
系列方法可能引起内存泄漏: 在ARC环境下,编译器并不知道将要调用的选择子是什么,有没有返回值,返回值是什么,所以ARC不能判断返回值是否能释放,因此ARC做了一个比较谨慎的做法:只添加retain
,不添加release
。因此在有返回值或参数的时候可能导致内存泄漏。 -
performSelector
系列方法的返回值只能是void或OC对象类型。 -
performSelector
系列方法最多只能传入两个参数。
因此可以使用GCD来代替 performSelector
系列方法:
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ //do something.. }); 复制代码
三、掌握GCD及操作队列的使用时机
GCD
性能很棒,但在执行后台任务时, GCD
并不一定是最佳选择。在iOS开发中,还有一种技术叫 NSOperationQueue
。 GCD
是基于 C语言 的API,性能较高。而 NSOperationQueue
是基于 GCD
的抽象。
使用 NSOperation
和 NSOperationQueue
的优点:
-
支持取消某个
NSOperation
: 在运行任务前,可以在NSOperation对象上调用cancel方法,用以表明此任务不需要执行。不过已经启动的任务无法取消。iOS 8之前,GCD队列是无法取消的,GCD是“安排好之后就不管了(fire and forget)”。iOS 8之后,支持dispatch_cancel
和dispatch_block_cancel
; -
NSOperation
支持多任务操作的依赖关系: 比如:任务A、B、C必须在任务D完成后执行。 -
支持通过
KVO
监控NSOperation
对象的属性: 例如:可以通过isCancelled
属性来判断任务是否已取消,通过isFinished
属性来判断任务是否已经完成等等; -
支持指定
NSOperationQueue
的优先级: 操作的优先级表示此操作与队列中其他操作之间的优先关系,优先级高的NSOperationQueue
先执行,优先级低的后执行。GCD的队列也有优先级,不过不是针对整个队列的; -
重用
NSOperation
对象: 在开发中你可以使用NSOperation
的子类或者自己创建NSOperation
对象来保存一些信息,可以在类中定义方法,使得代码能够多次使用;
四、通过Dispatch Group机制,根据系统资源状况来执行任务
dispatch group
是 GCD
的一项特性,能够把任务进行分组管理,然后等待这组任务执行完毕时会有通知,开发者可以拿到结果然后继续下一步操作。 另外,通过 dispatch group
在并发队列上同时执行多项任务的时候,GCD会根据系统资源状态来帮忙调度这些并发执行的任务。
五、使用dispatch_once来执行只需要运行一次的线程安全代码
例如:我们开发中写一个单例,就可以使用 dispatch_once
:
+ (instancetype)sharedInstance { static Class *manager = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ manager = [[Class alloc] init]; }); return manager; } 复制代码
以上所述就是小编给大家介绍的《iOS 编写高质量Objective-C代码(七)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 编写高质量Python程序(三)基础语法
- 如何编写高质量的函数 -- 命名/注释/鲁棒篇
- 编写高质量箭头函数的5个最佳做法
- iOS 编写高质量Objective-C代码(三)
- iOS 编写高质量Objective-C代码(二)
- iOS 编写高质量Objective-C代码(二)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
一本书读懂大数据
黄颖 / 吉林出版集团有限责任公司 / 2014-12-1
进入大数据时代,让数据开口说话将成为司空见惯的事情,书中将从大数据时代的前因后果讲起,全面分析大数据时代的特征、企业实践的案例、大数据的发展方向、未来的机遇和挑战等内容,展现一个客观立体、自由开放的大数据时代。一起来看看 《一本书读懂大数据》 这本书的介绍吧!