首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >iOS NSURLConnection (sendAsynchronousRequest:)缓存太多

iOS NSURLConnection (sendAsynchronousRequest:)缓存太多
EN

Stack Overflow用户
提问于 2014-12-28 17:32:10
回答 2查看 1.5K关注 0票数 2

我有几个内存泄漏(不!)参见我的应用程序中的更新1),它们都归结为异步URLRequest。下面的代码给了我一个内存泄漏,似乎‘数据’从来没有释放(下面的代码在我的应用程序中逻辑上没有使用,因为它是一个完全无用的无限循环,我写它只是为了显示内存泄漏。这使得使用的RAM在不到1秒的时间内从5 MB变为20 MB。我的互联网速度与此相匹配,只是为了记录一下):

代码语言:javascript
复制
- (void)start{
    NSOperationQueue *oQC = [[NSOperationQueue alloc] init];
    NSLog(@"a");
    [NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.online-image-editor.com//styles/2014/images/example_image.png"]] queue:oQC completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
        NSLog(@"b");
        [self start];
    }];
}

我也尝试过设置数据=零,但就像假设的那样,这是行不通的。有没有人知道如何避免内存泄漏,以及这是否是NSURLConnection的正常行为?

更新1:

这似乎与内存泄漏无关,而是与缓存问题有关。(感谢@rdelmar,他发现了这个问题,但他的解决方案不太奏效)

基于this post,我尝试在它的.h文件中创建一个新的“Loader”类:

代码语言:javascript
复制
#import <Foundation/Foundation.h>

@interface Loader : NSObject <NSURLConnectionDelegate, NSURLConnectionDataDelegate>

@property NSMutableData *mData;
@property (nonatomic, copy) void (^returnBlock)(NSData *data, NSError *error);

- (id)initForWhateverWithURLString:(NSString*)urlString andHandler:(void (^)(NSData *data, NSError *error))handler;

@end

在它的.m文件中:

代码语言:javascript
复制
#import "Loader.h"

@implementation Loader

@synthesize mData;

- (id)initForWhateverWithURLString:(NSString*)urlString andHandler:(void (^)(NSData *data, NSError *error))handler{
    self = [super init];
    if (self) {
        /*NSOperationQueue *oQC = [NSOperationQueue mainQueue];
        [NSURLConnection sendAsynchronousRequest:mUR queue:oQC completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
            [[NSURLCache sharedURLCache] removeCachedResponseForRequest:mUR];
            handler(nil, nil);
         }];*/
        mData = [NSMutableData new];
        self.returnBlock = handler;
        NSMutableURLRequest *mUR = [[NSURLRequest requestWithURL:[NSURL URLWithString:urlString] cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:60] mutableCopy];
        NSURLConnection *URLCon = [[NSURLConnection alloc] initWithRequest:mUR delegate:self];
        [URLCon start];
    }
    return self;
}

- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse{
    return nil;
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
    [mData appendData:data];
    data = nil;
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection{
    self.returnBlock(mData, nil);
    mData = nil;
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
    self.returnBlock(nil, error);
}

@end

我还实施了:

代码语言:javascript
复制
NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:0 diskCapacity:0 diskPath:@"nsurlcache"];
[NSURLCache setSharedURLCache:sharedCache];

尽管如此,这两种方法都没有帮助减少剧烈的RAM使用!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-12-29 22:20:20

我觉得你看到的不是泄密。我认为内存不断增加,因为数据正在被缓存。如果更改请求的缓存协议,问题就解决了(通过使用requestWithURL:)获得默认行为requestWithURL:)

代码语言:javascript
复制
- (void)viewDidLoad {
    [super viewDidLoad];
    self.req = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.online-image-editor.com//styles/2014/images/example_image.png"] cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:10];
    [self start];
}

- (void)start{
    NSOperationQueue *oQC = [NSOperationQueue mainQueue]; // this queue is where the completion block runs, so you should use mainQueue if you want to do any UI updating
    NSLog(@"a");
    [NSURLConnection sendAsynchronousRequest:self.req queue:oQC completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
        NSLog(@"b");
        [self start];
    }];
}

编辑后的

再看一看,我不知道为什么sendAsynchronousRequest:会导致内存使用量随着时间的增加而增加。我使用NSURLSession进行了测试(这也是我们现在应该使用的),而且这似乎没有增加内存。

代码语言:javascript
复制
- (void)viewDidLoad {
    [super viewDidLoad];
    NSString *urlString = @"http://www.online-image-editor.com//styles/2014/images/example_image.png";
    self.req = [NSURLRequest requestWithURL:[NSURL URLWithString:urlString] cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:10];
    [self start];
}

- (void)start{
    NSLog(@"a");
    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    NSURLSessionDataTask *task = [session dataTaskWithRequest:self.req completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        self.counter ++;
        NSLog(@"counter is: %ld", self.counter);
        [self start];
    }];
    [task resume];
}
票数 3
EN

Stack Overflow用户

发布于 2014-12-28 20:15:03

如果不使用ARC,则更改

代码语言:javascript
复制
[[NSOperationQueue alloc] init];

代码语言:javascript
复制
[[[NSOperationQueue alloc] init] autorelease];

代码语言:javascript
复制
[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.online-image-editor.com//styles/2014/images/example_image.png"]]

代码语言:javascript
复制
[[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.online-image-editor.com//styles/2014/images/example_image.png"]] autorelease]
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27678865

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档