Objective c 连接泄漏?
我已经建立了一个nsurl,它从http获取数据。 当我运行仪器时,它说我有一个泄漏NSFNetwork对象 如何释放选中的(无效)按钮中的连接?或者稍后会发布Objective c 连接泄漏?,objective-c,memory-management,memory-leaks,nsurlconnection,nsurlrequest,Objective C,Memory Management,Memory Leaks,Nsurlconnection,Nsurlrequest,我已经建立了一个nsurl,它从http获取数据。 当我运行仪器时,它说我有一个泄漏NSFNetwork对象 如何释放选中的(无效)按钮中的连接?或者稍后会发布 - (void)ButtonClicked { NSURLRequest *theRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:KmlUrl] cachePol
- (void)ButtonClicked {
NSURLRequest *theRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:KmlUrl]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:20.0f];
NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if (theConnection) {
// receivedData is declared as a method instance elsewhere
NSMutableData *receivedData = [[NSMutableData data] retain];
[self setKMLdata:receivedData];
} else {
// inform the user that the download could not be made
}
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
// append the new data to the receivedData
// receivedData is declared as a method instance elsewhere
[KMLdata appendData:data];
NSLog(@"didReceiveData");
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
// release the connection, and the data object
[connection release];
[KMLdata release];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
// release the connection, and the data object
[connection release];
// receivedData is declared as a method instance elsewhere
[KMLdata release];
}
这是一个常见的问题,通过[对象自动释放]的魔力可以解决。在您的代码中,这将如下所示:
NSURLConnection *theConnection = [[[NSURLConnection alloc] initWithRequest:theRequest delegate:self] autorelease];
通过这种方式,对象将自动添加到“自动释放池”中,并在不再引用该对象后在下一次运行循环开始时解除锁定
希望有帮助
编辑:另外,我不明白您为什么需要调用receivedData变量上的-retain。我终于找到了答案 上述代码中的错误(顺便说一句,这是来自的接近精确的示例)不在内存管理代码中。自动释放是一种选择,手动释放是另一种选择。无论如何处理NSURLConnection对象,使用NSURLConnection都会导致泄漏 首先,这里是解决方案。只需将这3行代码直接复制到ConnectionIDFinishLoading、didFailWithError和释放NSURLConnection对象的任何其他地方
NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:0 diskCapacity:0 diskPath:nil];
[NSURLCache setSharedURLCache:sharedCache];
[sharedCache release];
该代码归功于mpramodjain
问题似乎是这样的——SDK将请求和回复缓存在iPhone上。即使您的NSMutableURLRequest cachePolicy设置为不从缓存加载回复,也会出现这种情况
愚蠢的是,默认情况下,它似乎缓存了大量数据。我正在传输大量数据(分成多个连接),并开始收到内存警告,最后我的应用程序死掉了
我们需要的文档位于NSURLCache(非NSURLConnection)中,它们声明:
NSURLCache实现了
对URL加载请求的响应
将NSURLRequest对象映射到
nsCachedUrResponse对象。这是一个
由内存中的和
在磁盘缓存上
提供了一些方法来操作
每个缓存的大小也是如此
以控制要使用的磁盘上的路径
用于缓存数据的持久存储
这三条线的作用是完全破坏缓存。将它们添加到我的应用程序()后,我的活体计数保持稳定。您好,您测试过此委托方法吗
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse
{
return nil;
}
您可以更精确地管理缓存
“重置”NSURLCache*sharedCache可能会导致代码的其他部分出现问题?我使用的是静态方法/自动重置方法,它似乎工作正常:
[NSURLConnection connectionWithRequest:theRequest delegate:self];
这样,您甚至不必担心在委托回调中释放。事实证明,在上面的示例中分配连接后,连接的保留计数实际上是2(不是1),这改变了我对内存“泄漏”的看法
@rpetrich我实际上不认为您需要担心在释放连接之前释放委托。连接保留它的委托,而连接本身实际上由某种开放连接队列保留。我在博客上写了一篇关于我的NSURLConnection实验的博文:
调用autorelease将起作用,但在释放连接之前释放委托的情况下,调用autorelease将失败。更好的方法是将连接分配给实例变量,并在不需要时释放+nil。如果在对象解除分配时仍分配了连接ivar,则需要在释放连接之前将委托设置为nil。@rpetrich我同意您的建议更全面,然而,很明显,他的问题显示了对iPhone内存管理的基本误解,因此我想给他一个概念上更简单的解释solution@rpetrich,你能提供一个代码示例吗。我已经用很多方法解决了这个问题,但仍然存在漏洞。@rpetrich,是的,我也想看看你的例子。为了记录在案,我切换到了autorelease'd[NSURLConnectionWithRequest:request delegate:self],但我认为这不重要。如果你的应用程序发出任何其他NSURLConnection请求,应该使用缓存,此解决方案将禁用它们。在这种情况下,更好的解决方案可能是实现缓存响应委托(具有相同的效果):
-(NSCachedURLResponse*)连接:(NSURLConnection*)连接将缓存响应:(NSCachedURLResponse*)缓存响应{return nil;}
进一步了解实际发生的情况:NSURLCache正在缓存对请求的响应,但它使用请求作为密钥。因此,只要缓存响应,它就会保留请求。一个0字节的缓存会破坏这一点,代价是让应用程序发出的所有请求都不缓存;实现委托方法是一种更为定制的方法。将请求的缓存策略设置为忽略缓存是不够的。如果您不想完全禁用缓存,并且不能或不想使用与委托的异步连接,则可以调用[[NSURLCache sharedullcache]removeCachedResponseForRequest:request]代码>发送请求后,我正在使用+[NSURLConnection sendAsynchronousRequest:queue:completionHandler:]和+[NSURLConnection sendSynchronousRequest:returningResponse:error]以及您设置缓存的方法,但是,仅在这些方法上,活动字节不断增加,最终我的应用程序在>30 Mb后被杀死。你知道吗?对于sendSynchronousRequest,我使用串行队列在dispatch\u async中执行此操作。谢谢