关于block块使用的6点注意事项

对于刚学习OC新伙伴,block块一直都是一个比较纠结、比较难懂的知识点,不过,在使用一段时间后,就会感觉很酸爽。block块的原理及使用我就不再赘述,网上有很多这方面的资料。我个人使用这么长时间以来,觉得使用block块应该注意以下几点。

一、在使用block前需要对block指针做判空处理

例如:XXXX为定义的block块

if (XXXX ) {                  if(XXXX != nil){
XXXX(参数);            或  XXXX(参数); 
}                                }

#在使用block块,最好对block进行判空处理,不进行判空处理直接使用的话,一旦指针为空就会直接产生崩溃。

二、block如果作为属性变量时,要copy一下,将栈上的block拷贝到堆上

例如,作为属性时,写成@property (nonatomac,copy)XXXXXX;(注:XXXXXX为block块)

#如果不进行copy,若是栈上的block被释放,此block块属性变量就为空了,程序有可能就会直接产生崩溃。

三、在block使用之后要对block指针做赋空值处理,如果是MRC的编译环境下,要先release掉block对象。

#block作为类对象的成员变量,使用block的人有可能用类对象参与block中的运算而产生循环引用。

将block赋值为空,是解掉循环引用的重要方法。(不能只在dealloc里面做赋空值操作,这样已经产生的循环引用不会被破坏掉)
例如:if (_sucBlock ) {
  _sucBlock(参数);
  }
  //MRC下:要先将[_sucBlock release];(之前copy过)
  _sucBlock = nil; //在使用之后将Block赋空值,解引用 !!!
   }

还有一种改法,在block接口设计时,将可能需要的变量作为形参传到block中,从设计上解决循环引用的问题。

四、使用时将self或成员变量加入block之前要先将self变为__weak弱引用,这与第三条其实是一个问题,就是解决循环引用问题。

五、在多线程环境下(block中的weakSelf有可能被析构的情况下),需要先将self转为strong指针,避免在运行到某个关键步骤时self对象被析构。

#第四、第五条合起来有个名词叫weak–strong dance

以下代码来自AFNetworking,堪称使用weak–strong dance的经典。

__weak typeof(self) weakSelf = self;
AFNetworkReachabilityStatusBlock callback = ^(AFNetworkReachabilityStatus status) {
__strong typeof(weakSelf) strongSelf = weakSelf;
strongSelf.networkReachabilityStatus = status;
if (strongSelf.networkReachabilityStatusBlock) {
strongSelf.networkReachabilityStatusBlock(status);
}
};

第一行:__weak __typeof(self)weakSelf = self;
如之前第四条所说,为防止callback内部对self强引用,weak一下。
其中用到了__typeof(self),这里涉及几个知识点:
a. __typeof、__typeof__、typeof的区别
没有区别
b.对于老的LLVM编译器上面这句话会编译报错,所以在很早的ARC使用者中流行__typeof(&*self)这种写法

第三行:__strong typeof(weakSelf) strongSelf = weakSelf;

按照之前第五条的说法给转回strong了,这里typeof()里面写的是weakSelf,里面写self也没有问题,因为typeof是编译时确定变量类型,所以这里写self 不会被循环引用。

第四、五、六行,如果不转成strongSelf而使用weakSelf,后面几句话中,有可能在第四句执行之后self的对象可能被析构掉,然后后面的StausBlock没有执行,导致逻辑错误。

最后第五行,使用前对block判空。

六、block回调不起作用,可能是调用block属性变量的类的实例对象已不是原来的对象。

#这个问题只能具体情况具体分析了,程序运行可能不会错,就是block回调不起作用,有些功能实现不了,断点调试发现根本不走回调。之前我有一个同事就遇到过这个问题,另外一个同事给他解决了一个小时也没解决,我让他检查一下调用block块的类对象,果然,与原来的地址不是一个,他又新建一个对象,前后就花了1分钟解决(得意一下)。

其他问题继续总结中,也希望朋友们将自己遇到的问题分享一下??。

时间: 2024-11-18 02:58:04

关于block块使用的6点注意事项的相关文章

iOS之block块

Block块. 1.声明Block int (^myBlock)(int n) = ^(int num) 类型 (^名称)(需要传的参数)= ^(参数) 2 __block 变量 在block块中修改block块外部变量的值,只有将外部的变量前面加_ _(两个短杠才能修改) 3 __weak 变量 在ARC机制下,如果block中应用控制器对象或者其实例变量,block会对其强引用,导致拷贝一份控制器对象从而造成内存泄露.为了避免这一问题,则需要: __weak typeof(self)weak

Linux内核系列之Block块层(一)

.Block块层入口函数为 genhd_device_init(),先对该函数开始分析: 函数实现源码: static int __init genhd_device_init(void) {     bdev_map = kobj_map_init(base_probe, &block_subsys_lock);     blk_dev_init();     subsystem_register(&block_subsys);     return 0; }   .kobj_map_i

ARC中block块作为属性的使用笔记

ARC中block块作为属性的使用笔记 block较难理解,根据在内存中的分布情况就分为3种类型,根据使用的情形又分为很多很多种.虽然用起来容易,但使用不当会造成内存泄露,虽然都是这么说,但你真的研究过为什么会泄露吗?为什么有些时候外部变量进入block的时候会导致引用计数+1呢? 本人做过MRC以及ARC的开发,但大势所趋,ARC将是以后开发的主要模式,即使有MRC也是ARC混编MRC的代码,所以,本文的block的一些使用上的心得都基于ARC的,已经不考虑MRC的了,请看官注意,MRC与AR

【学习ios之路:Objective-C】block块语法.NSDate和NSDateFormatter

一.Block块语法 块语法:可以在函数内部定义匿名函数 格式: ^返回值类型(参数列表){函数体}其中返回值类型可以省略 block简单练习: ①.求两个数的最大值 //int (^)(int,int)//block类型 int (^max)(int,int) = ^(int a,int b) {//block的实现体 return a > b ? a : b; }; int value = max(4,6);          printf("%d",value); ②.将一

Objective-c中的Block(块)详解

Block初探 在Objective-c中NSArray是很常用的容器之一,很多时候我们需要对数组中的数据进行排序,因此与下面类似的代码会经常碰到: NSArray *sortedArray = [array sortedArrayUsingComparator: ^(id obj1, id obj2) { if ([obj1 integerValue] > [obj2 integerValue]) { return (NSComparisonResult)NSOrderedDescending

「ios」block块中使用self

[问题现象] 在block块中使用self时报警告:self strongly in this block is likely to lead to a retain cycle [问题解决] __block ViewController *blockSelf = self;_block = ^{ [blockSelf->_items addObject:@"Hello!"];};

黑马程序员-2.block块

吐槽:刚开始接触iOS的时候真的挺不适应的,里面出现了很多新玩意,不过还好我比较喜欢新鲜事物,以后整理些iOS中比较新颖的东西. block就是一个,不过有了block之后省去了上下翻代码的麻烦,很好用,推荐!! 1.Block定义 Block是OC中的一种数据类型,在iOS开发中被广泛使用 ^是Block的特有标记,Block的实现代码包含在{}之间 大多情况下,以内联inline函数的方式被定义和使用 Block与C语言的函数指针有些相似,但使用起来更加灵活 示例 void(^demoBlo

oracle BBED 直接改动数据库block块

1.BBED配置 1)将相应文件放到$ORACLE_HOME/rdbms/mesg和$ORACLE_HOME/rdbms/lib中: --将lib中bbedus.msb和bbedus.msg 放在$ORACLE_HOME/rdbms/mesg下 --将lib中sbbdpt.o和ssbbded.o 放在$ORACLE_HOME/rdbms/lib下 2)安装BBED --在$ORACLE_HOME/rdbms/lib下运行: [[email protected] lib]$ make -f ins

Block --- 块语法

block 块语法.  --- 匿名函数 block可以在函数内部定义匿名函数. blocK -- 实现两个数的最大值. 函数: #import <Foundation/Foundation.h> #import "Person.h" //1.输出I love ios void output() { printf("I love ios\n"); } //2.求两个数的最大 int maxValue(int x, int y) { return x &g