众所周知,闭包(Closures)的使用可以很大的简化我们的代码,也可以让我们更容易的写出更具逻辑性的代码。但如果使用不当就容易产生循环引用,进而产生内存泄漏。我们往往在闭包中使用[weak self]来避免循环引用的产生,但是否所有的闭包都应该使用[weak self]呢,其中又有哪些注意点呢?
闭包中是否需要使用[weak self]的判断法则
image1.逃逸闭包与非逃逸闭包
非逃逸闭包:没有赋值于存储变量、立即执行、没有传递给其他闭包;
逃逸闭包:赋值于存储变量、在未来某个时间点执行、传递给其他闭包;
2.是否可以接受延迟释放持有闭包的对象
当闭包中有比较耗时的操作(比如图片处理)或者闭包内操作做了延迟处理,那么如果闭包中包含持有该闭包的对象,将产生该对象延迟释放的问题。比如ViewController中有个闭包执行图片的处理,那么当dismiss后,ViewController有可能在一段时间内不会被回收,直到闭包执行完毕。
这种问题不会带来内存泄漏,但如果viewcontroller在dismiss后,在一段不可预估的时间内不能被置为nil,往往会带来不可预估的问题,这种情况下,我们需要使用[weak self]。另一方面,如果你要确保闭包里的这段代码必须完整的执行,即使ViewController被dismiss,那么我们可以不使用[weak self]。
3.基于判断准则的一些示例
一些高阶函数 或者 立刻执行的Animation,他们属于没有耗时操作的非逃逸闭包,可以不使用[weak self]
image image赋值于某个存储变量,在未来某个时间点执行,他们属于逃逸闭包,需要使用[weak self]
image我们可以将闭包中操作的对象参数当作一个引用传递给闭包,这样也可以在不使用[weak self]的情况下避免内存泄漏
image当我们在闭包中使用GCD的时候,一般也不需要使用[weak self],除非我们把闭包赋值给存储变量并且没有立即执行该闭包。
image和GCD类似,当我们在闭包中执行URLSession的调用时,除非我们把闭包赋值给存储变量并且没有立即执行该闭包。但是由于URLSession任务的执行往往是耗时的操作,这时候我们就会遇到是否需要延时释放对象的问题了。
image直接将A对象的一个方法赋值给B对象闭包属性时,往往忽略[weak self]的使用,不经意间就产生了循环引用:
image其中self持有printingButton,closure又持有self。
【关注公众号 发现更多精彩】
网友评论