我运行乐器工具并获得一些内存泄漏,我不知道如何处理这个问题。我正在使用ARC!
这是我的代码:
+ (MARequest *)requestImageThumb:(NSString *)imageName
object:(NSInteger)objectId {
NSString* urlString = [NSString stringWithFormat:@"%@/%@", kBaseImageThumbURL, imageName];
LogTrace(@"Creating image thumb request for file %@", imageName);
//Here starts the leak!!
return [MARequest createWithURL:[NSURL URLWithString:urlString]
type:REQUEST_TYPE_GET_IMAGE];
}
+ (MARequest *)createWithURL:(NSURL *)url
type:(NSInteger)type {
MARequest* r = [[MARequest alloc] init];
r.url = url;
r.requestType = type;
r.responseData = [[NSMutableData alloc] init];
r.connection = [[NSURLConnection alloc] initWithRequest:[NSURLRequest requestWithURL:r.url]
delegate:r
startImmediately:NO];
return r;
}
这是我的NSURLConnectionDelegate
#pragma mark - NSURLConnectionDelegate
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
LogTrace(@"request %@: didReceiveResponse", self.url);
[self.responseData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
LogTrace(@"request %@: didReceiveData, %d bytes", self.url, data.length);
[self.responseData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
LogTrace(@"request %@: didFailWithError: %@", self.url, [error description]);
self.connection = nil;
self.failed = YES;
[self invokeAction];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
LogTrace(@"request %@: connectionDidFinishLoading, %d bytes", self.url, [self.responseData length]);
self.connection = nil;
[self invokeAction];
}
修改
我现在把我的代码更改为了这个,但遗憾的是它仍然给了我一个内存泄漏......
+ (MARequest *)requestImageThumb:(NSString *)imageName
object:(NSInteger)objectId {
NSString* urlString = [NSString stringWithFormat:@"%@/%@", kBaseImageThumbURL, imageName];
LogTrace(@"Creating image thumb request for file %@", imageName);
return [MARequest requestWithURL:[NSURL URLWithString:urlString]
type:REQUEST_TYPE_GET_IMAGE];
}
+ (MARequest *)requestWithURL:(NSURL *)url
type:(NSInteger)type {
MARequest* r = [[MARequest alloc] init];
r.url = url;
r.requestType = type;
r.responseData = [[NSMutableData alloc] init];
r.connection = [[NSURLConnection alloc] initWithRequest:[NSURLRequest requestWithURL:r.url]
delegate:r
startImmediately:NO];
return r;
}
答案 0 :(得分:2)
编辑:更改后,泄漏的解释如下:
您的GFRequest
对象与NSURLConnection
对象之间存在循环依赖关系,因此无法正确释放这两者。实际上,您要将GFRequest
的连接属性设置为NSURLConnection
实例:
r.connection = [[NSURLConnection alloc] initWithRequest:[NSURLRequest requestWithURL:r.url]
同时也让r
成为NSURLConnection
的代表:
delegate:r
NSURLConnection
's delegate does a retain on its delegate会发生什么,这会导致依赖性循环。
但是,我没有看到一种简单的方法来打破依赖性,并保留您当前的设计。
您可以简单地避免在请求中存储连接,或者您无法将请求用作连接的委托。可能,您应该考虑子类化NSURLConnection
的可能性,并让它充当自己的委托。
老答案:
外部方法名称与内部名称之间存在不匹配:
+ (MARequest *)requestImageThumb:(NSString *)imageName
…
return [MARequest createWithURL:[NSURL URLWithString:urlString]
对于静态分析器,它们具有与对象所有权不同的语义。
将第一个替换为:
+ (MARequest *)createRequestImageThumb:(NSString *)imageName
或第二个:
return [MARequest requestWithURL:[NSURL URLWithString:urlString]
取决于适合您的语义。
答案 1 :(得分:1)
听起来就是你已经用create
这个词启动了方法,它向ARC表明它将返回一个保留计数为1的对象。换句话说,create
表示调用者将在完成后释放对象。
然后你直接在另一个 not 以create
开头的方法中返回这个对象。这表明如果第二种方法的调用者应该保留该对象,如果它想要保留它。
这里存在冲突,我认为ARC不知道该怎么做。它应该是否释放物体?
如果您将+createWithURL:type:
重命名为+requestWithURL:type:
,则应该修复它,因为+requestWithURL:type:
将返回一个自动释放的对象,这是+requestImageThumb:object:
期望返回的对象。
或者,将+requestImageThumb:object:
重命名为+createRequestWithImageThumb:object:
,明确要求+createRequestWithImageThumb:object:
返回保留对象,该对象来自+createWithURL:type:
。