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

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

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

  1. iOS之block块

    Block块. 1.声明Block int (^myBlock)(int n) = ^(int num) 类型 (^名称)(需要传的参数)= ^(参数) 2 __block 变量 在block块中修改 ...

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

    .Block块层入口函数为 genhd_device_init(),先对该函数开始分析: 函数实现源码: static int __init genhd_device_init(void) {     ...

  3. 定义block块

    一: 工程图 二: 代码区 AppDelegate.h #import <UIKit/UIKit.h> @interface AppDelegate : UIResponder <U ...

  4. Objective-C中的block块语法

    #import <Foundation/Foundation.h> /* OC不同于Java C++ 它没有字符串对象 只有NS对象 NS就是乔布斯第一个公司NeXt的类集合 被收购之后才 ...

  5. 初探swift语言的学习笔记(闭包 - 匿名函数或block块代码)

    很多高级语言都支持匿名函数操作,在OC中的block也为大家所熟悉,然面在swift里好像是被重新作了一个定义,不叫匿名函数,或 block了,而叫闭包(closure).下面配合代码来理解一下swi ...

  6. iOS开发之使用block块进行数据遍历的方法

    看了一篇文章,发现遍历数组.字典中的数据时,除了使用for循环外,还可以使用block块进行操作,瞬间感觉iOS的语言代码确实有点高大上的感觉,下面就简单的介绍一下这个方法. 首先是最基本的运用形式, ...

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

    ARC中block块作为属性的使用笔记 block较难理解,根据在内存中的分布情况就分为3种类型,根据使用的情形又分为很多很多种.虽然用起来容易,但使用不当会造成内存泄露,虽然都是这么说,但你真的研究 ...

  8. Linux_僵尸进程、挂载、block块、inode号

    僵尸进程: 基本概念: 进程分为父进程和子进程 父进程一死 子进程都会死 杀死主进程的时候  子进程也会被杀死 僵尸进程:主进程被杀死了  但是子进程还活着    子进程不会占用cpu但还是会占着内存 ...

  9. hdfs深入:03、hdfs的架构以及副本机制和block块存储

    HDFS分布式文件系统设计目标 1.            硬件错误  由于集群很多时候由数量众多的廉价机组成,使得硬件错误成为常态 2.            数据流访问  所有应用以流的方式访问数 ...

随机推荐

  1. 浅谈Xcode5和Xcode7在系统创建的文件夹和文件中的区别

    *:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...

  2. 中断下半部-tasklet

    http://edsionte.com/techblog/ tasklet的实现 tasklet(小任务)机制是中断处理下半部分最常用的一种方法,其使用也是非常简单的.正如在前文中你所知道的那样,一个 ...

  3. sunlime操作

    ctrl+p 查找文件  @进行符号查找ctrl+h 替换文件 选中字符以后多次按 ctrl+D 跳过则按 ctrl+Kctrl+shift+d 复制多行alt+f3 多选 ctrl+shift+p ...

  4. Ganglia系列(一)安装

    安装前条件:能够上网,安装了yum 1.系统版本: Red Hat Enterprise Linux Server release 6.3 x86_64位 2.Ganglia版本 ganglia-3. ...

  5. JS自定义事件(Dom3级事件下)

    原文出处:  http://www.w3cfuns.com/notes/11861/e21736a0b15bceca0dc7f76d77c2fb5a.html . 我拿出作者中的一段,感谢作者原创. ...

  6. Android 各种MIME类型和文件类型的匹配表

    MIME:全称Multipurpose Internet Mail Extensions,多功能Internet 邮件扩充服务.它是一种多用途网际邮件扩充协议,在1992年最早应用于电子邮件系统,但后 ...

  7. android_自定义布局

    1.需要实现view类 2.如果需要实现自定义属性则: 1.定义资源文件attrs---->values 2. <?xml version="1.0" encoding ...

  8. Android Fragment 生命周期

    启动的事件触发顺序 F Fragmeent A Activity onAttach(F) onAttachFragment(A) onCreate(F) onCreateView(F) onActiv ...

  9. Could not find class &#39;****&#39;, referenced from method #####

    找不到类,多半也是和第三方的jar包有关. 将找不到的类.在下图中的地方勾选出来.假设jar太多.有的类有冲突的话,须要明白其先后顺序. 请外一篇和第三方jar有关的异常的文章. Conversion ...

  10. MySQL::SQL_MODE

    SQL_MODE可能是比较容易让开发人员和DBA忽略的一个变量,默认为空.SQL_MODE的设置其实是比较冒险的一种设置,因为在这种设置下可以允许一些非法操作,比如可以将NULL插入NOT NULL的 ...