CFTypeRef 使用中容易造成的内存泄漏样例一则
最近老修一些内存泄漏问题,真是尴尬。
BlocksKit 中遇到的问题
__weak typeof(self) weakSelf = self;
[btn bk_addEventHandler:^(id sender) {
if (_activity.source == ATASyncTypeInvitation) {
ATAViewActivityInvitationViewController *vc = (ATAViewActivityInvitationViewController *)[[ATAViewActivityInvitationViewController alloc] initWithActivity:_activity];
[weakSelf.navigationController pushViewController:vc animated:YES];
} else {
ATAEditCalendarEventViewController *vc = [[ATAEditCalendarEventViewController alloc] initWithActivity:_activity];
[weakSelf.navigationController pushViewController:vc animated:YES];
}
} forControlEvents:UIControlEventTouchUpInside];
这段代码看起来没有问题,但是在实际中却遇到了 Controller 无法回收的尴尬。像前一篇Block 中循环引用导致内存泄漏样例一则提到的那样,加上 weak 修饰本来就可以万事大吉还是出了问题。所以问题在哪里呢?
原来是调用了_activity
导致的,改成weakSelf.activity
就好了,或者把 activity
做一份 weak 版本也行。
CFTypeRef 其实是 MRC
ARC 时代的人可能都不知道 MRC 怎么用的,很可惜 CoreFoundation
框架下的对象全是需要手动释放的。
也就是说
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
这样通过 xxxxxCreate
函数生成并自己持有的对象是需要自己手动调用 CFRelease
来释放,否则会内存泄漏。
然而
ABRecordRef abRecordRef = [participant ABRecordWithAddressBook:addressBook];
这却不能调用 CFRelease
函数来释放,因为这个函数生成的对象自己并不持有,不能释放自己不持有的对象。这个函数在生成对象并 return 的时候将对象注册到了 AutoReleasePool 延长生命周期,只要 pool 生命周期结束其内的对象跟着一起销毁。