1.在ARC中为什么block会导致循环引用
我们知道在一个类中定义了一个block的属性值completionHandler,那么这个类就对completionHandler拥有所有权,也就是对这个completionHandler强引用,如果在completionHandler块语句里面使用self.xx,此时这个block块就对self拥有了所有权,也就是对当前类强引用,这样就会造成循环引用,导致当前类无法释放。对于解决方法,我们看苹果的官方文档是这样讲的:
在手动引用技术的模式下, __block id x,不会保留x。在ARC模式下, __block id x;默认会保留x(就像其它值一样)。为了在ARC下达到手动引用技术的效果,你可以使用 __unsafe__unretained __block id x ;然而,就像 __unsafe_unretained名字蕴含的那样,拥有一个未保留变量(non-retained variable)是危险的(因为他可能是一个野指针),因此最好不要使用。有两个更好的选择是要么使用 __weak(如果你不需要支持IOS4或OS X v10.6),要么设置 __block值nil来打破循环引用。
如上所述,你可以使用 __block限定符来替代,并在 completion处理方法中将myController的值设置为nil:
或者,你可以使用一个临时的 __weak变量。以下代码列举了一个简单的实现:
2.关于gcd队列
并发队列:允许多个任务同时执行。
串行队列:任务按顺序依次执行。
//全局队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{
/*任务a */
NSLog(@"任务a完成\n");
NSLog(@"任务a完成\n");
NSLog(@"任务a完成\n");
NSLog(@"任务a完成\n");
});
NSLog(@"先完成a\n");
dispatch_group_async(group, queue, ^{
/*任务b */
NSLog(@"任务b完成\n");
NSLog(@"任务b完成\n");
NSLog(@"任务b完成\n");
NSLog(@"任务b完成\n");
});
NSLog(@"先完成b\n");
dispatch_group_async(group, queue, ^{
/*任务c */
NSLog(@"任务c完成\n");
});
NSLog(@"先完成c\n");
dispatch_group_async(group, queue, ^{
/*任务d */
NSLog(@"任务d完成\n");
});
NSLog(@"先完成d\n");
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
// 在a、b、c、d异步执行完成后,会回调这里
NSLog(@"任务a,b,c,d完成\n");
});
下面我们查看下打印结果:
2017-11-07 14:18:23.774764+0800 TabbariOSTest[2789:742111] 先完成a
2017-11-07 14:18:23.774812+0800 TabbariOSTest[2789:742801] 任务a完成
2017-11-07 14:18:23.774904+0800 TabbariOSTest[2789:742111] 先完成b
2017-11-07 14:18:23.774910+0800 TabbariOSTest[2789:742801] 任务a完成
2017