这是一个非常奇怪的错误。
如果下载完成,我使用代码下载NSURLConnection
的文件,我没有泄漏。
但是如果我取消下载,我就会释放1Mo内存。
我已经用仪器进行了测试,并确定了产生这种泄漏的方法
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
真的很奇怪
这是我创建,管理和取消下载的代码
注意:此下载是核心数据管理对象的一部分,但我认为核心数据不对我的泄漏负责。
- (void)loadURL:(NSURL *)url
{
if (currentLoadingDatas) { // just bool for prevent multiple download
return;
}
currentLoadingDatas = YES;
NSURLRequest *request = [[NSURLRequest alloc]
initWithURL: url
cachePolicy: NSURLRequestReloadIgnoringLocalAndRemoteCacheData
timeoutInterval: 60
];
connectionDatas = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[request release];
}
#pragma mark NSURLConnection Delegates
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
if (!self.transientData) {
self.transientData = [[NSMutableData alloc] init];
}
[self.transientData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[self.transientData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
[self willChangeValueForKey:@"datas"];
[self setValue:self.transientData forKey:@"datas"];
[self didChangeValueForKey:@"datas"];
[self.transientData release];
NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:0 diskCapacity:0 diskPath:nil];
[NSURLCache setSharedURLCache:sharedCache];
[sharedCache release];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:0 diskCapacity:0 diskPath:nil];
[NSURLCache setSharedURLCache:sharedCache];
[sharedCache release];
}
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse
{
return nil;
}
-(void)cancelDownload
{
[self.connectionDatas cancel];
}
// fired by coreData
-(void)willTurnIntoFault
{
self.transientData = nil;
[self cancelDownload];
[super willTurnIntoFault];
}
// fired by coreData
-(void)didTurnIntoFault
{
[connectionDatas release];
NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:0 diskCapacity:0 diskPath:nil];
[NSURLCache setSharedURLCache:sharedCache];
[sharedCache release];
[self.transientData release];
[super didTurnIntoFault];
}
你能帮我找出问题吗?
非常感谢。
答案 0 :(得分:2)
如何声明self.transientData
属性?
因为您使用:self.transientData = [[NSMutableData alloc] init];
进行初始化,并且如果将属性设置为保留该值,则需要将其释放两次。
如果是,请设置属性使用:self.transientData = [[[NSMutableData alloc] init] autorelease];
或仅[NSMutableData data];
剩下的对我来说似乎没问题。
答案 1 :(得分:1)
泄漏表明您的变量在该点被实例化,因此泄漏实际上并不是它开始的位置。您需要在取消方法中释放transientData,如此
- (void)cancelDownload
{
[self.connectionDatas cancel];
self.transientData = nil;
}
您的编码风格存在一些不一致的问题,这可能会让您更难以精神上追踪正在发生的事情。如果你坚持自己的标准,那么应该更容易遵循流程。
这可能会发生另一次泄密
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
if (!self.transientData) {
self.transientData = [[NSMutableData alloc] init]; // leaky line
}
[self.transientData setLength:0];
}
[[NSMutableData alloc] init]
来电正在创建NSMutableData
的实例,保留计数为+1。然后,如果您使用retain
的属性(最好),则self.transientData =
将另外保留为保留计数添加另外+1。这只是后来才发布一次,因为NSMutableData
仍然会闲置,因此你会有泄漏。
在代码中进一步使用模式
这是我不在init
方法时使用的模式。因此,之前的方法应改为:
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
if (!self.transientData) {
NSMutableData *tmpTransientData = [[NSMutableData alloc] init];
self.transientData = tmpTransientData;
[tmpTransientData release];
}
[self.transientData setLength:0];
}
这样做的好处是不使用自动释放,因此您可以更明确地知道何时不再需要该对象,这在具有较小内存的设备上是可取的。
另一个可能有益于整理的不一致是你如何释放你的ivars。您已在代码中交替完成此操作
[self.transientData release];
self.transientData = nil;
我会在我的代码中使用后者(不在dealloc
中)用于实例变量,因为synthesized
setter会为你调用release
并将指针设置为{{1这是相当安全的。