使用iVar初始化自定义类导致内存泄漏 - iOS

时间:2016-01-13 07:23:15

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

我有一个名为RequestController的类,它负责下载,解析数据并将它们放在一个可从父级访问的强属性数组中。

这里的问题是初始化RequestController的方法不止一次执行并且使用Allocations我注意到它发生了内存泄漏并且对象永远不会被释放。 RequestController变量是一个iVar。 RequestController还有一个委托给父控制器。

RequestController.h

#import <Foundation/Foundation.h>

//================

@protocol RequestControllerDelegate <NSObject>

@required
- (void)RequestControllerRequestSuccessful:(NSInteger)mode;
- (void)RequestControllerRequestFailedWithError:(NSInteger)code;

@end

//=================

@interface RequestController : NSObject <NSURLSessionDataDelegate>

@property (nonatomic, assign) id <RequestControllerDelegate> delegate;

@property(nonatomic,strong)NSMutableArray *resultArray;
@property(nonatomic,strong)NSMutableArray *purposesArray;

-(instancetype)initAndRegisterUserWithTelephone:(NSString*)tel Delegate:(id<RequestControllerDelegate>)del;
-(void)nulifyArrays;

@end

RequestController.m

中初始化对象
@implementation RequestController{

        NSURLSession *conn;
        NSArray *responseArray;
        NSMutableData *responseData;
        NSString *reqEmail;

}
@synthesize delegate,resultArray;

#pragma mark - Init Functions
-(instancetype)initAndRegisterUserWithTelephone:(NSString*)tel Delegate:(id<RequestControllerDelegate>)del{



    self = [super init];

    if (self) {

        currentMode=RQRegisterMode;

        self.delegate=del;

        //Check for internet connection
        bool internet = [self internetConnectivity];

        //Sending the requests on the server
        if(internet){

            NSString* url = [NSString stringWithFormat:@"%@/someurlwithparams",API_URL];

            NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10];

            NSString *param= [NSString stringWithFormat:@"method=%@",tel];

            NSData *requestBodyData = [param dataUsingEncoding:NSUTF8StringEncoding];

            request.HTTPBody = requestBodyData;

            // Specify that it will be a POST request
            request.HTTPMethod = @"POST";


            NSURLSessionConfiguration *sessionConfig =[NSURLSessionConfiguration defaultSessionConfiguration];
            conn = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:[NSOperationQueue mainQueue]];

            NSURLSessionDataTask *dataTask= [conn dataTaskWithRequest:request];
            [dataTask resume];
        }

        else
        {

            //No internet connection
            [delegate RequestControllerRequestFailedWithError:RCNoInternetError];

        }



    }
    return self;

}

在父控制器中,我将对象初始化为:

req = [[RequestController alloc]initAndRegisterUserWithTelephone:fullTel Delegate:self];

我有这些代表:

-(void)RequestControllerRequestSuccessful:(NSInteger)mode{
    [SVProgressHUD dismiss];
    [self manageError:NoError];
   //Copying the data to local variable
  self.array = [NSMutableArray alloc]initWithArray:[req resultArray]];

}

-(void)RequestControllerRequestFailedWithError:(NSInteger)code{
    [SVProgressHUD dismiss];
    [self manageError:code];

}

到目前为止一直很好,但是一旦我重新初始化RequestController,我就会发生内存泄漏。 我在这里做错了什么?

更新1 这条线导致泄漏:

conn = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:[NSOperationQueue mainQueue]];

更新2

self替换nil正在解决问题但是我需要 NSURLSession

的代表

2 个答案:

答案 0 :(得分:0)

问题是我在完成任务后没有使NSURLSession无效。

Apple:

  

一旦失效,就会引用委托和回调对象   破碎。失效后,会话对象无法重复使用。

所以我在代表中完成任务后使用{{1}},泄漏消失了。

答案 1 :(得分:-1)

尝试使用:AFNetWorking

  

AFNetworking是适用于iOS和Mac OS X的令人愉快的网络库。

Singleton,我认为是处理服务器请求的最佳方式。

这在RequestManager.h中:

#import <Foundation/Foundation.h> 

@interface RequestManager : NSObject

    + (RequestManager *)sharedClass;

    - (void)registerUserWithTelephone:(NSString *)tel
                              success:(void(^)(BOOL finished, NSArray *JSONResponse))success;

这在RequestManager.m中:

#import "RequestManager.h"
#import "AFNetworking.h"

@implementation RequestManager

static RequestManager *sharedClassInstance = nil;

+ (RequestManager *) sharedClass {
        @synchronized(self) {
            if (!sharedClassInstance)
                sharedClassInstance = [[RequestManager alloc] init];
            return sharedClassInstance;
        }
 }

- (void)registerUserWithTelephone:(NSString *)tel
                          success:(void(^)(BOOL finished, NSArray *JSONResponse))success{

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];

manager.responseSerializer = [AFHTTPResponseSerializer serializer];
manager.requestSerializer = [AFHTTPRequestSerializer serializer];

NSString *URLString = @"URL STRING";

NSDictionary *parameters = @{@"PARAMETER NAME" : tel};

[manager POST:URLString parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {

    NSError *error = nil;
    NSArray *data = [NSJSONSerialization JSONObjectWithData:responseObject
                                                    options:0
                                                      error:&error];
    success(YES, data);


} failure:^(AFHTTPRequestOperation *operation, NSError *error) {

    NSData *errorData = error.userInfo[AFNetworkingOperationFailingURLResponseDataErrorKey];
    NSDictionary *serializedData = [NSJSONSerialization JSONObjectWithData:errorData options:kNilOptions error:nil];

    NSLog(@"RequestManager error code %ld",[operation.response statusCode]);

}];

}

你可以在这样的控制器中得到它:

#import "RequestManager.h"

[[RequestManager sharedClass] registerUserWithTelephone:telNumberString
                              success:^(BOOL finished, NSDictionary *JSONResponse){

NSLog(@"%@", JSONResponse);

}];

这是我在我的应用中使用的那种代码。