【问题标题】:NSURLConnection Memory LeakNSURLConnection 内存泄漏
【发布时间】:2014-08-13 16:01:10
【问题描述】:

我运行仪器工具并得到一些内存泄漏,我不知道如何处理这个问题。我正在使用 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;
}

【问题讨论】:

  • 请再次显示静态编译​​器输出...
  • 我加了两张截图,希望对你有帮助!
  • 能否请您显示 GFRrequest 接口定义?顺便说一句,你注意到泄漏不是原来的地方......

标签: ios objective-c memory-management memory-leaks nsurlconnection


【解决方案1】:

编辑:更改后,泄漏的解释如下:

您的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]

取决于哪种语义适合您的情况。

【讨论】:

  • 非常感谢,遗憾的是我仍然有泄漏,请参阅我的编辑!
【解决方案2】:

听起来发生的事情是,您已经使用单词 create 启动了该方法,这向 ARC 表明它将返回一个保留计数为 1 的对象。换句话说,create 表明调用者完成后将负责释放对象。

然后你直接在另一个create开头的方法中返回这个对象。这表明如果第二个方法的调用者想要保留该对象,是否应该保留它。

这里有冲突,我认为 ARC 不知道该怎么做。它应该释放对象吗?

如果您将+createWithURL:type: 重命名为+requestWithURL:type:,这应该可以解决它,因为+requestWithURL:type: 将返回一个自动释放的对象,这是+requestImageThumb:object: 期望返回的。

或者,将+requestImageThumb:object: 重命名为+createRequestWithImageThumb:object: 以明确要求+createRequestWithImageThumb:object: 返回一个从+createWithURL:type: 获取的保留对象。

【讨论】:

  • 非常感谢,这是有道理的,但它仍然给我一个漏洞,请参阅我的编辑:)
猜你喜欢
  • 2023-04-08
  • 1970-01-01
  • 2011-09-07
  • 2011-03-21
  • 1970-01-01
  • 1970-01-01
  • 2010-11-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多