六、block与GCD

1, 块Block 是C, C++, OC 中的词法闭包

2,块可以接受参数,可以返回值

3, 块可以分配字栈上,也可以分配在堆上,也可以是全局的。分配在栈上的块可以拷贝在堆里,这样的话,就和标准的OC对象一样,具备了引用计数

----  定义块的时候,其所占的内存区域是分配在栈中

执行Copy 方法后,复制到堆上了

38,为常用的块类型创建typedef

1,以typedef重新定义块类型,可令块变量用来更加简单

2,定义新类型时,应遵从先用的命名习惯,不要使用其名称与别的类型相冲突

3, 可以为同一块签名定义多个类型别名,如果要重构的代码用了块类型的某个别名,那么只需修改相应的块签名即可,无需改动其他typedef


39,用hander块降低代码分散程度

1, 在创建对象的时候,可以使用内联的hander块江相关业务逻辑一并说明

2, 在有多个实例监控时,如果采用委托模式,那么经常需要根据传入的对象来切换,而若使用hander块来实现,则可以直接将块与相关对象放在一起

3,设计API 时,如果用到了hadner块,那么可以增加一个参数,是调用者可通过此参数来决定应该安排在哪个队列执行

40,用块应用其所属对象时,不用出现保留环

1, 如果块所捕获的对象直接或间接的保留了块本身,那么就要当心保留环的问题

2, 一定要找个适当的时机解除保留环,而不能把责任推给API调用者

在API实现的方法里,如果调用了实例变量,就会出现保留环。打破保留环的方法是,在适当的时候,= nil

41, 多用派发队列,少用同步锁

1,派发队列可用来表述同步语义,这种做法要比使用 @syncheonized块 或NSLock对象更加简单

2,将同步和异步派发结合起来,可以实现与普通加锁机制一样的同步行为,而这么做却不会阻塞执行异步派发的线程

3, 使用同步队列和栅栏块,可以另同步更加高效

实例变量

42,多用GCD,少用performSelector方法

1,performSelector 系列方法在内存管理方面容易有疏失。它无法确定要执行的选择子具体是什么,因而ARC编译器也就无法插入适当的内存管理方法

2,performSelector系列方法所能处理的选择子太过局限了,选择子的返回类型及发送给参数的方法的参数个数都受到限制

3,如果想把任务放在另一个线程中执行, 那么最好不要使用performSelector系列方法,而应该把任务封装在块里,然后调用GCD的相关方法实现

43,掌握GCD及操作队列的使用时机

1,在解决多线程和任务管理问题时,派发队列(GCD)并非唯一方法

2,操作队列(NSOperation)提供了一套高层的 OC  API,能实现纯GCD 所具备的绝大部分功能,而且还能完成更为复杂的操作,那些操作若改用GCD实现,则需要另外编写代码

44,通过Dispatch Group机制,更具系统资源情况来执行

dispatch_queue_t queue = dispatch_get_global_queue(0, 0);

dispatch_group_t group = dispatch_group_create();

void(^block1)() = ^(){

for(inti = 0; i < 1000; i++) {

NSLog(@"%@--- > block1 + %d", [NSThread currentThread], i);

}

};

void(^block2)() = ^(){

for(inti = 0; i < 1000; i++) {

NSLog(@"%@--- >--- > block2 + %d", [NSThread currentThread], i);

}

};

void(^block3)() = ^(){

for(inti = 0; i < 1000; i++) {

NSLog(@"%@--- >--- >--- > block3 + %d", [NSThread currentThread], i);

}

};

dispatch_group_async(group, queue, block1);

dispatch_group_async(group, queue, block2);

dispatch_group_async(group, queue, block3);

dispatch_group_notify(group, dispatch_get_global_queue(0, 0), ^{

NSLog(@"%@结束了", [NSThread currentThread]);

});

45,使用dipatch_once来执行只需运行一次的线程安全代码

1, 经常需要编写‘只需执行一次的线程安全代码’。通过GCD所提供的dispatch_once函数,很容易就能实现此功能

2,编译应该声明在static 或者 global 作用域中,这样的话,在把只需执行一次的块传给 dispatch_once 函数,传进去的标记也是相同的

+(instancetype)shareManager

{

static dispatch_once_tpred;

static BluetoothLEService* manager =nil;

dispatch_once(&pred, ^{

manager = [[BluetoothLEService alloc] init];

manager.arrFilterName= [@[@"WATER-",@"Cupcare-"]mutableCopy];

});

return manager;

}

46, 不用使用 dispatch_get_current_queue

1, dispatch_get_current_queue 函数的行为常常与开发者的预期不同。此函数已经废弃,只用做调试使用

2, 由于派发队列是按层级来组织的,所有无法单用某个队列对象来描述‘当前队列‘这个概念

3, dispatch_get_current_queue 函数用于解决由不可重入的代码所引起的死锁,然后能用这个函数解决的问题,通常也能使用队列特定数据’来解决

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • NSThread 第一种:通过NSThread的对象方法 NSThread *thread = [[NSThrea...
    攻城狮GG阅读 869评论 0 3
  • 41.多用派发队列,少用同步锁 在Objective-C中,如果有多个线程要执行同一份代码,那么有时可能会出问题。...
    Code_Ninja阅读 1,190评论 1 13
  • 1. GCD简介 什么是GCD呢?我们先来看看百度百科的解释简单了解下概念 引自百度百科:Grand Centra...
    千寻_544f阅读 424评论 0 0
  • 3.GCD GCD的全称是Grand Central Dispatch,提供了非常多的纯C语言的函数 GCD的优势...
    Mario_ZJ阅读 524评论 0 0
  • 是我的世界太过单纯,还是你们的世界太过繁华。
    莫跨界阅读 170评论 0 0