前言
本篇文章精讲iOS开发中使用Block时一定要注意内存管理问题,很容易造成循环引用。本篇文章的目标是帮助大家快速掌握使用block的技巧。
我相信大家都觉得使用block给开发带来了多大的便利,但是有很多开发者对block内存管理掌握得不够好,导致经常出现循环引用的问题。对于新手来说,出现循环引用时,是很难去查找的,因此通过Leaks不一定能检测出来,更重要的还是要靠自己的分析来推断出来。
声景一:Controller之间block传值
现在,我们声明两个控制器类,一个叫ViewController,另一个叫HYBAController。其中,ViewController有一个按钮,点击时会push到HYBAController下。
先看HYBAController:
1
2
3
4
5
6
7
|
// 公开了一个方法
-
(
instancetype
)
initWithCallback
:
(
HYBCallbackBlock
)
callback
;
// 非公开的属性,这里放出来只是告诉大家,HYBAController会对这个属性强引用
@property
(
nonatomic
,
copy
)
HYBCallbackBlock
callbackBlock
;
|
下面分几种小场景来看看循环引用问题:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
@interface
ViewController
(
)
// 引用按钮只是为了测试
@property
(
nonatomic
,
strong
)
UIButton
*button
;
// 只是为了测试内存问题,引用之。在开发中,有很多时候我们是
// 需要引用另一个控制器的,因此这里模拟之。
@property
(
nonatomic
,
strong
)
HYBAController
*vc
;
@end
// 点击button时
-
(
void
)
goToNext
{
HYBAController
*vc
=
[
[
HYBAController
alloc
]
initWithCallback
:
^
{
[
self
.
button
setTitleColor
:
[
UIColor
greenColor
]
forState
:UIControlStateNormal
]
;
}
]
;
self
.
vc
=
vc
;
[
self
.
navigationController
pushViewController
:vc
animated
:YES
]
;
}
可以简单说,这里形成了两个环:
对于此这问题,我们要解决内存循环引用问题,可以这么解: 不声明vc属性或者将vc属性声明为weak引用的类型,在callback回调处,将self.button改成weakSelf.button,也就是让callback这个block对viewcontroller改成弱引用。如就是改成如下,内存就可以正常释放了:
笔者尝试过使用Leaks检测内存泄露,但是全是通过,一个绿色的勾,让你以为内存处理得很好了,实际上内存并得不到释放。 针对这种场景,给大家提点建议:
这样的话,只要日志没有打印出来,说明内存得不到释放,就需要学会分析内存引用问题了。 场景二:Controller与View之间Block传值我们先定义一个view,用于与Controller交互。当点击view的按钮时,就会通过block回调给controller,也就反馈到控制器了,并将对应的数据传给控制器以记录:
接下来看HYBAController,增加了两个属性,在viewDidLoad时,创建了aView属性:
关于上一场景所讲的循环引用已经解决了,因此我们这一小节的重点就放在controller与view的引用问题上就可以了。 |