我一定误解了一些内存管理规则,因为当我尝试修复内存泄漏时,App崩溃了。让我给你看一些代码:
calendarRequestLog是单个对象中MutableDictionary类型的属性,只要App运行就存在。这是.h文件中的声明:
@property (nonatomic, retain, readonly) NSMutableDictionary *calendarRequestLog;
我用(在init中)分配它:
calendarRequestLog = [[NSMutableDictionary alloc] init];
我用它填充它(注意保留,这会造成内存泄漏):
[calendarRequestLog setObject:[[NSMutableArray arrayWithObject:delegate] retain] forKey:date];
我有时会用它来访问它:
NSMutableArray* delegates = [calendarRequestLog objectForKey:date];
if(delegates != nil) {
// add delegates
}
我把它清空:
NSMutableArray* delegates = [calendarRequestLog objectForKey:date];
if(delegates != nil) {
for (id <ServerCallDelegate> delegate in delegates) { … }
// clear the request from the log
[calendarRequestLog removeObjectForKey:date];
}
以下是删除上面的保留时崩溃的代码:
NSMutableArray* delegates = [calendarRequestLog objectForKey:date];
if(delegates != nil) {
if([delegates containsObject:delegate]) // crash
[delegates removeObject:delegate];
}
崩溃是因为代理被解除分配但不是零。更准确地说,我得到一个EXC_BAD_ACCESS异常。
所有这些方法可以按不同顺序或多次调用。
我无法弄清楚,为什么会这样。我认为,集合应该保留它们的对象 - 因为这个数组对象(委托)仍然在集合中,所以它不应该被释放。其他代码不负责任,我向你展示了所有出现的calendarRequestLog。
我感谢所有帮助!
@Edit 我想我明白了。
当委托被取消分配时,我调用了崩溃方法,以便我不会在以后的事故中调用委托。
但是:我在calendarRequestLog中保留了委托,所以只要不调用它就不能取消分配:
// clear the request from the log
[calendarRequestLog removeObjectForKey:date];
...反过来,取消分配委托并调用崩溃方法。由于calendarRequestLog已经删除了代理,但还没有删除密钥,我们崩溃了。
好的,我会以不同的方式解决这个问题。感谢所有评论 - 多亏了你,我看了看其他地方!
答案 0 :(得分:0)
您是否尝试在抓取时保留,以便在您使用它时没有人释放您的物体?
NSMutableArray* delegates = [[calendarRequestLog objectForKey:date] retain];
if(delegates != nil) {
if([delegates containsObject:delegate]) // crash
[delegates removeObject:delegate];
}
[delegates release];
答案 1 :(得分:-1)
通常的做法如下,因为您已经保留在.h文件中:
//create local instance, then copy that to the class wide var
NSMutableDictionary *_calendarRequestLog = [NSMutableDictionary alloc] init];
self.calendarRequestLog = _calendarRequestLog;
[_calendarRequestLog release];
另外,我真的不明白为什么你会留在这里:
[calendarRequestLog setObject:[[NSMutableArray arrayWithObject:delegate] retain] forKey:date];
为什么不将其改为:
[calendarRequestLog setObject:[NSMutableArray arrayWithObject:delegate] forKey:date];
答案 2 :(得分:-3)
改为写
calendarRequestLog = [[NSMutableDictionary alloc] init];
此
self.calendarRequestLog = [NSMutableDictionary dictionary];
并尝试使用属性而不是ivar