有关block使用的5点注意事项

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

对于刚学习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分钟解决(得意一下)。

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

对于刚学习OC新伙伴,block块一直都是一个比较纠结、比较难懂的知识点,不过,在使用一…

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

第四、第五条合起来有个名词叫weak–strong dance,来自于2011 WWDC Session
#322 (Objective-C Advancements in
Depth)

};

恩~~他们没有区别,但是这牵扯一段往事,在早期C语言中没有typeof这个关键字,__typeof、__typeof__是在C语言的扩展关键字的时候出现的。

如果上面Network类设计成这个样子:

写在最后,阅读好的开源库源码是提高个人水平的一个很好途径,看见不懂的地方去查去摸索会得到更多。1、在使用block前需要对block指针做判空处理。

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

}

@classNetowrkClass;

写在最后,阅读好的开源库源码是提高个人水平的一个很好途径,看见不懂的地方去查去摸索会得到更多。

typedefvoid(^SuccBlock)(iddata);@interfaceNetworkClass {

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

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

}@end

typedefvoid(^SuccBlock)(NetworkClass
*aNetworkObj,iddata);@interfaceNetworkClass//…@end@implementationNetworkClass@end@implementationUserCode-
(void) temporaryNetworkCall

a. __typeof、__typeof__、typeof的区别

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

4、使用方将self或成员变量加入block之前要先将self变为__weak

SuccessBlock _sucBlock;

Review一下上面这段代码,里面玄机不少。

__strong __typeof(weakSelf)strongSelf=weakSelf;

NetworkClass*netObj =[[NetworkClass alloc] init];

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

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

图片 1

__weak __typeof(self)weakSelf =self;

{

}else{

{

}

第一行:__weak __typeof(self)weakSelf = self;

}];

}

strongSelf.networkReachabilityStatusBlock(status);

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

}

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

其中用到了__typeof(self),这里涉及几个知识点:

typeof是现代GNU
C++的关键字,从Objective-C的根源说,他其实来自于C语言,所以AFNetworking使用了继承自C的关键字。

不判空直接使用,一旦指针为空直接产生崩溃。

__strong __typeof(weakSelf)strongSelf=weakSelf;

大致说法是老LLVM编译器会将__typeof转义为 XXX类名 *const
__strong的__strong和前面的__weak关键字对指针的修饰又冲突了,所以加上&*对指针的修饰。

}@end

4、使用方将self或成员变量加入block之前要先将self变为__weak

}//MRC下:要先将[_sucBlock release];(之前copy过)_sucBlock =
nil;//Importent: 在使用之后将Block赋空值,解引用
!!!}@end//=======================以下是使用方===========================@implementationUserCode-
(void) temporaryNetworkCall

图片 2

将block赋值为空,是解掉循环引用的重要方法。(不能只在dealloc里面做赋空值操作,这样已经产生的循环引用不会被破坏掉)

}@end

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

[netObj requestWithSucBlock:^(NetworkClass *aNetworkObj,iddata)
{//这里参数中已经有netObj的对象了,使用者不用再从block外引用指针了。if(aNetworkObj.propertyUseInCallBack
==YES) {//Do Something…}

}iddata =[NSKeyedUnarchiver unarchiveObjectWithFile:[self
favoriteFile]];if([data isKindOfClass:[NSMutableArrayclass]]) {

AFNetworkReachabilityStatusBlock callback= ^(AFNetworkReachabilityStatus
status) {

AFNetworkReachabilityStatusBlock callback= ^(AFNetworkReachabilityStatus
status) {

}//MRC下:要先将[_sucBlock release];(之前copy过)_sucBlock =
nil;//Importent: 在使用之后将Block赋空值,解引用
!!!}@end//=======================以下是使用方===========================@implementationUserCode-
(void) temporaryNetworkCall

typeof是现代GNU
C++的关键字,从Objective-C的根源说,他其实来自于C语言,所以AFNetworking使用了继承自C的关键字。

typedefvoid(^SuccBlock)(iddata);@interfaceNetworkClass {

}];

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

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

图片 3

}

{

不判空直接使用,一旦指针为空直接产生崩溃。

}];

_sucBlock(data);

netObj.propertyUseInCallBack=NO;

图片 4

发表评论

电子邮件地址不会被公开。 必填项已用*标注