我的算法非常简单。将项添加到缓存。该项目存储在NSMutableArray
和NSMutableDictionary
中。该数组用作FIFO队列,如果我传递指定的最大大小,我删除最旧的项目,直到大小低于允许的最大值。
当我删除一个项目时,我首先从数组中删除if,然后从字典中删除。然后我遇到问题,因为项目似乎被过度释放(所以调试器说,“似乎”似乎没有指向有效的对象“)。
- (void) addItem:(NSData *)value forKey:(NSString *)key {
ApiResponseCacheItem *item = [[ApiResponseCacheItem alloc] init];
item.cacheKey = key;
item.cacheValue = value;
[queue addObject:item];
[item release];
[dictionary setObject:item forKey:key];
size += [value length];
while (size > kMaxCacheSize && [queue count] > 0) {
ApiResponseCacheItem *oldestItem = [queue objectAtIndex:0];
size -= [oldestItem.cacheValue length];
// remove oldest item
[queue removeObjectAtIndex:0];
[dictionary removeObjectForKey:oldestItem.cacheKey];
}
}
现在,我改变了顺序:首先我从字典中删除对象,然后从数组中删除,其他所有内容完全相同。现在一切都很好。
while (size > kMaxCacheSize && [queue count] > 0) {
ApiResponseCacheItem *oldestItem = [queue objectAtIndex:0];
size -= [oldestItem.cacheValue length];
[dictionary removeObjectForKey:oldestItem.cacheKey];
// remove oldest item
[queue removeObjectAtIndex:0];
}
请解释。
答案 0 :(得分:4)
此代码:
[queue addObject:item];
[item release];
[dictionary setObject:item forKey:key];
发布后,您正在使用item
。你永远不应该这样做。在[item release];
之后移动[dictionary setObject:item forKey:key];
:
[queue addObject:item];
[dictionary setObject:item forKey:key];
[item release];
答案 1 :(得分:1)
所以,首先@WTP是绝对正确的,你应该接受他的回答。 +1给他。
正确的做法是在发布之后不要触摸'item'。当你已经释放它之后,当然不会将它传递给其他毫无疑问的方法。
但是,话虽如此,如果你想理解为什么命令会对你是否幸存下来产生影响,关键是要记住NSDictionary不保留其密钥,复制它们强>
所以崩溃序列是这样的:
错误没有出现的幸运序列:
同样,你应该做@WTP建议的事情。如果你很好奇,这只是背景信息。希望有所帮助。