在分析这个问题之前,我们先列出下面这个图,并且理清它们的关系:
这里的setting控制器是指:ILSettingViewController,它在.h文件中定义了一个数组变量
@interface ILSettingViewController: UIviewViewController <UITableViewDataSource, UITableViewDelegate>
{
NSMutableArray *_allGroups; // 所有的组模型
}
@end
_allGroups存放的是ILSettingGroup对象,ILSettingGroup.h文件代码如下:
// ILSettingGroup.h
#import <Foundation/Foundation.h>
@interface ILSettingGroup : NSObject
@property (nonatomic, copy) NSString *header; // 头部标题
@property (nonatomic, copy) NSString *footer; // 尾部标题
@property (nonatomic, strong) NSArray *items; // 中间的条目
@end
ILSettingGroup的items数组存放的是ILSettingItem对象,ILSettingItem的.h文件为
#import <Foundation/Foundation.h>
typedef enum {
ILSettingItemTypeNone, // 什么也没有
ILSettingItemTypeArrow, // 箭头
ILSettingItemTypeSwitch // 开关
} ILSettingItemType;
@interface ILSettingItem : NSObject
@property (nonatomic, copy) NSString *icon;
@property (nonatomic, copy) NSString *title;
@property (nonatomic, assign) ILSettingItemType type;// Cell的样式
@property (nonatomic, copy) void (^operation)() ; // 点击cell后要执行的操作
+ (id)itemWithIcon:(NSString *)icon title:(NSString *)title type:(ILSettingItemType)type;
@end
而ILSettingItem.m文件如下所示
#import "ILSettingItem.h"
@implementation ILSettingItem
+ (id)itemWithIcon:(NSString *)icon title:(NSString *)title type:(ILSettingItemType)type
{
ILSettingItem *item = [[self alloc] init];
item.icon = icon;
item.title = title;
item.type = type;
return item;
}
@end
从前面的代码@property (nonatomic, copy) void (^operation)() ; 中可知,在copy形式下的代码块是存放在堆里面的,只有当ILSettingItem 对象销毁的时候,block才会销毁。此时如果代码块中引用了外部的对象,如下面这段代码(该段代码是控制器ILSettingViewController的代码)中的self(ILSettingViewController)对象,会对这个对象(self)进行强引用,从而产生文章刚开始所示图中的死循环,发生内存泄漏
// 1.1.推送和提醒
ILSettingItem *push = [ILSettingItem itemWithIcon:@"MorePush" title:@"推送和提醒" type:ILSettingItemTypeArrow];
push.operation = ^{
ILPushNoticeViewController *notice = [[ILPushNoticeViewController alloc] init];
[self.navigationController pushViewController:notice animated:YES];
};
所以,要想上面这一段代码不产生内存泄漏,需要做以下操作:
ILSettingItem *push = [ILSettingItem itemWithIcon:@"MorePush" title:@"推送和提醒" type:ILSettingItemTypeArrow];
_weak ILSettingViewController *setting = self;//把self变成一个弱引用,从而避免死循环,解决内存泄漏
push.operation = ^{
ILPushNoticeViewController *notice = [[ILPushNoticeViewController alloc] init];
[setting.navigationControllerpushViewController:notice animated:YES];
};