在IOS中使用Web服务时会发生NSURLSession内存泄漏 [英] NSURLSession Memory Leaks occur when using web services in IOS

查看:98
本文介绍了在IOS中使用Web服务时会发生NSURLSession内存泄漏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在构建一个使用Web服务的应用程序,并从我使用的Web服务获取信息 NSURLSession NSURLSessionDataTask

I am building an app that uses a web service and to get information from that web service I use NSURLSession and NSURLSessionDataTask.

我现在处于内存测试阶段,我发现 NSURLSession 导致内存泄漏。

I am now in the memory testing phase and I have found that NSURLSession is causing memory leaks.

这不是所有泄漏。这就是我能够适应的情况。

以下是我如何设置 NSURLSession 并从Web服务请求信息。

Below is how I setup the NSURLSession and request the information from the web service.

#pragma mark - Getter Methods

- (NSURLSessionConfiguration *)sessionConfiguration
{
    if (_sessionConfiguration == nil)
    {
        _sessionConfiguration = [NSURLSessionConfiguration ephemeralSessionConfiguration];

        [_sessionConfiguration setHTTPAdditionalHeaders:@{@"Accept": @"application/json"}];

        _sessionConfiguration.timeoutIntervalForRequest = 60.0;
        _sessionConfiguration.timeoutIntervalForResource = 120.0;
        _sessionConfiguration.HTTPMaximumConnectionsPerHost = 1;
    }

    return _sessionConfiguration;
}

- (NSURLSession *)session
{
    if (_session == nil)
    {
        _session = [NSURLSession
                    sessionWithConfiguration:self.sessionConfiguration
                    delegate:self
                    delegateQueue:[NSOperationQueue mainQueue]];
    }

    return _session;
}

#pragma mark -


#pragma mark - Data Task

- (void)photoDataTaskWithRequest:(NSURLRequest *)theRequest
{

#ifdef DEBUG
    NSLog(@"[GPPhotoRequest] Photo Request Data Task Set");
#endif

    // Remove existing data, if any
    if (_photoData)
    {
        [self setPhotoData:nil];
    }

    self.photoDataTask = [self.session dataTaskWithRequest:theRequest];

    [self.photoDataTask resume];
}
#pragma mark -


#pragma mark - Session

- (void)beginPhotoRequestWithReference:(NSString *)aReference
{
#ifdef DEBUG
    NSLog(@"[GPPhotoRequest] Fetching Photo Data...");
#endif

    _photoReference = aReference;

    NSString * serviceURLString = [[NSString alloc] initWithFormat:@"%@/json?photoreference=%@", PhotoRequestBaseAPIURL, self.photoReference];

    NSString * encodedServiceURLString = [serviceURLString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

    serviceURLString = nil;

    NSURL * serviceURL = [[NSURL alloc] initWithString:encodedServiceURLString];

    encodedServiceURLString = nil;

    NSURLRequest * request = [[NSURLRequest alloc] initWithURL:serviceURL];

    [self photoDataTaskWithRequest:request];

    serviceURL = nil;
    request = nil;
}

- (void)cleanupSession
{
#ifdef DEBUG
    NSLog(@"[GPPhotoRequest] Session Cleaned Up");
#endif

    [self setPhotoData:nil];
    [self setPhotoDataTask:nil];
    [self setSession:nil];
}

- (void)endSessionAndCancelTasks
{
    if (_session)
    {
#ifdef DEBUG
        NSLog(@"[GPPhotoRequest] Session Ended and Tasks Cancelled");
#endif

        [self.session invalidateAndCancel];

        [self cleanupSession];
    }
}

#pragma mark -


#pragma mark - NSURLSession Delegate Methods

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
#ifdef DEBUG
    NSLog(@"[GPPhotoRequest] Session Completed");
#endif

    if (error)
    {
#ifdef DEBUG
        NSLog(@"[GPPhotoRequest] Photo Request Fetch: %@", [error description]);
#endif

        [self endSessionAndCancelTasks];

        switch (error.code)
        {
            case NSURLErrorTimedOut:
            {
                // Post notification
                [[NSNotificationCenter defaultCenter] postNotificationName:@"RequestTimedOut" object:self];
            }
                break;

            case NSURLErrorCancelled:
            {
                // Post notification
                [[NSNotificationCenter defaultCenter] postNotificationName:@"RequestCancelled" object:self];
            }
                break;

            case NSURLErrorNotConnectedToInternet:
            {
                // Post notification
                [[NSNotificationCenter defaultCenter] postNotificationName:@"NotConnectedToInternet" object:self];
            }
                break;

            case NSURLErrorNetworkConnectionLost:
            {
                // Post notification
                [[NSNotificationCenter defaultCenter] postNotificationName:@"NetworkConnectionLost" object:self];
            }
                break;

            default:
            {

            }
                break;
        }
    }
    else {

        if ([task isEqual:_photoDataTask])
        {
            [self parseData:self.photoData fromTask:task];
        }
    }
}

- (void)URLSession:(NSURLSession *)session didBecomeInvalidWithError:(NSError *)error
{
    if (error)
    {

#ifdef DEBUG
        NSLog(@"[GPPhotoRequest] Session Invalidation: %@", [error description]);
#endif

    }

    if ([session isEqual:_session])
    {
        [self endSessionAndCancelTasks];
    }
}

#pragma mark -


#pragma mark - NSURLSessionDataTask Delegate Methods

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
{

#ifdef DEBUG
    NSLog(@"[GPPhotoRequest] Received Data");
#endif

    if ([dataTask isEqual:_photoDataTask])
    {
        [self.photoData appendData:data];
    }
}

#pragma mark -

问题:
为什么 NSURLSession 导致这些内存泄漏?当我完成它时,我使 NSURLSession 无效。我也发布了我不需要的任何属性并将会话设置为nil(参考 - (void)cleanupSession& - (void)endSessionAndCancelTask​​s)。

Question: Why is NSURLSession causing these memory leaks? I am invalidating the NSURLSession when I am finished with it. I am also releasing any properties that I do not need and setting the session to nil (refer to - (void)cleanupSession & - (void) endSessionAndCancelTasks).

其他信息:
会话完成并清理后发生内存泄漏。有时,它们也会在我弹出 UIViewController 之后出现。但是,我的所有自定义(GPPhotoRequest和GPSearch)对象和UIViewController都被释放了(我已经确定添加了一个NSLog)。

Other Information: The memory leaks occur after the session has completed and "cleaned up". Sometimes, they also occur after I have popped the UIViewController. But, all of my custom (GPPhotoRequest and GPSearch) objects and UIViewController are being dealloced (I've made sure by adding an NSLog).

我试图不发布到很多代码,但我觉得大部分都需要被看到。

I tried not to post to much code, but I felt like most of it needed to be seen.

如果您需要更多信息,请告诉我。非常感谢帮助。

Please let me know if you need any more information. Help is greatly appreciated.

推荐答案

重读 URL加载系统编程指南它转变为我是将 NSURLSession 属性设置为nil得太早。

After rereading the URL Loading System Programming Guide it turns that I was setting the NSURLSession property to nil too early.

相反,我需要设置 NSURLSession 属性为nil我收到委托消息 URLSession:(NSURLSession *)session didBecomeInvalidWithError:(NSError *)error ,这是有意义的。幸运的是,这是一个小错误。

Instead, I need to set the NSURLSession property to nil AFTER I receive the delegate message URLSession:(NSURLSession *)session didBecomeInvalidWithError:(NSError *)error, which makes sense. Luckily, it was a minor mistake.

例如

- (void)URLSession:(NSURLSession *)session didBecomeInvalidWithError:(NSError *)error
{
    if (error)
    {

#ifdef DEBUG
        NSLog(@"[GPPhotoRequest] Session Invalidation: %@", [error description]);
#endif

    }

    if ([session isEqual:_session])
    {
        [self cleanupSession];
    }
}

这篇关于在IOS中使用Web服务时会发生NSURLSession内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆