【问题标题】:Initialization a custom class with iVar causing memory leak - iOS使用 iVar 初始化自定义类导致内存泄漏 - iOS
【发布时间】:2016-01-13 07:23:14
【问题描述】:

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

这里的问题是初始化RequestController 的方法被执行了不止一次并且使用分配我注意到它发生了内存泄漏并且对象永远不会被释放。 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

nil 替换self 可以解决问题,但我需要NSURLSession

的代表

【问题讨论】:

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


    【解决方案1】:

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

    苹果:

    一旦失效,对委托和回调对象的引用将 破碎的。失效后,会话对象不能再使用。

    所以我在代表中完成任务后使用了[conn invalidateAndCancel],并且泄漏消失了。

    【讨论】:

      【解决方案2】:

      尝试使用: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);
      
      }];
      

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

      【讨论】:

      • 感谢您的回答。我知道 AFNetworking,但我的问题是关于解决内存泄漏问题。
      猜你喜欢
      • 2019-11-24
      • 1970-01-01
      • 2021-09-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-17
      相关资源
      最近更新 更多