2013-08-29 40 views
0

我上传图像块智慧,在后台线程,每个块将大小为512kb,据我所知,我已经照顾使用版本,nsautoreleasepool内存泄漏的照顾。 以下是上传图片chunkwise的代码。NSThread导致内存泄漏iPhone

- (void)FetchDataFromDB : (NSNumber *) isOffline 
{ 
@autoreleasepool { 
    @try { 
    NSLog(@"FetchDatafromDB"); 
    isThreadStarted = YES; 

    VYukaDBFunctions *vdb = [VYukaDBFunctions getInstance]; 

    NSMutableArray *fileNames = [vdb GetFileNames:[isOffline integerValue]]; 
    for(int j=0 ; j<[fileNames count] ; j++) 
    { 

     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
     NSString * filename = fileNames [j] ; 
     int _outgoingMsgId = [[vdb SelectMsgId:filename] intValue]; 
     int _totalchunk =[[vdb SelectTotalChunk:filename]intValue]; 
     int currentChunk = [vdb GetCurrentChunk:filename]; 
    for(int i=currentChunk ; i <= _totalchunk ; i++) 
    { 

     NSAutoreleasePool *innerPool = [[NSAutoreleasePool alloc] init]; 

     NSString *AsyncRequest = [[NSString alloc] init]; 
     AsyncRequest = [vdb SelectAsyncRequest: i : _outgoingMsgId]; 

     if(![AsyncRequest isEqual:@""]) 
     { 

     BOOL status = [self UploadChunkWise :AsyncRequest : 1 : i : vdb : filename : _outgoingMsgId]; 
     // AsyncRequest = NULL; 
    // [AsyncRequest release]; 
     if(status){ 
      if(i==_totalchunk) 
      { 
       NSLog(@"Deleting from medialist , FileName :%@", filename); 
       [vdb DeleteFromMediaList : filename]; 

      } 
     } 
     else{ 

      [vdb DeleteFromMediaList : filename]; 
      break; 
     } 
     } 

     [innerPool drain]; 
    } 

     [pool drain]; 
    } 

    [fileNames removeAllObjects]; 

    // [fileNames release]; 

    //recurssive call to check any pending uploads.. 
    if([[vdb GetFileNames:[isOffline integerValue]] count] > 0) 
    { 
     NSLog(@"Calling Recursively.."); 
     [self FetchDataFromDB:[isOffline integerValue]]; 
    } 

    } 
    @catch (NSException *exception) { 

     NSLog(@"Exception caught on Uploading from FetchDataFromDB:%@", exception); 

    } 
    @finally { 

    } 
} 

NSLog(@"thread quit "); 
isThreadStarted = NO; 
[NSThread exit]; 

} 

-(BOOL) UploadChunkWise :(NSString *) AsyncRequest : (int) count : (int)currentChunk : (VYukaDBFunctions *) vdb : (NSString *) currentFileName : (int) outgoingMsgId 
{ 

NSHTTPURLResponse *response ; 
NSError *error; 
//Yes, http 
NSMutableURLRequest *httpRequest = [[NSMutableURLRequest alloc] initWithURL:[NSURL  URLWithString:@"Url goes here"]]; 
NSData* data = [AsyncRequest dataUsingEncoding:NSUTF8StringEncoding]; 

[httpRequest setHTTPMethod:@"POST"]; 
[httpRequest setHTTPBody:data]; 

[httpRequest setValue:@"application/xml" forHTTPHeaderField:@"Content-Type"]; 
NSData *returnedData = [NSURLConnection sendSynchronousRequest: httpRequest returningResponse:&response error:&error] ; 
NSString *result= [[NSString alloc] initWithData:returnedData encoding:NSASCIIStringEncoding]; 
[httpRequest release]; 

returnedData= NULL; 
[returnedData release]; 
data = NULL; 
[data release]; 

if ([result rangeOfString:@"success"].location != NSNotFound) 
{ 
    NSLog(@" success"); 
    [vdb DeleteCurrentChunkFromOutgoingTable:currentChunk : outgoingMsgId]; 
    [result release]; 
    return YES ; 

} 
else if ([result rangeOfString:@"fail"].location != NSNotFound) 
{ 
    [result release]; 
    if (count < 3) { 

     return [self UploadChunkWise :AsyncRequest : count+1 : currentChunk: vdb : currentFileName : outgoingMsgId ]; 
    } 
    else 
    { 
     NSLog(@" failed"); 
     [vdb DeleteAllCurrentFileChunksFromOutgoingTable:currentFileName]; 
     return NO ; 
    } 

} 

return NO; 

} 

我开始线程如下

[NSThread detachNewThreadSelector:@selector(FetchDataFromDB:) toTarget:self withObject:[NSNumber numberWithInt:0]]; 

问题是上传9〜12块后,我收到内存错误。我得到4至5倍的内存警告,然后在应用程序崩溃。在控制台我收到内存警告第一次在应用程序委托类,其次是扩展UIViewController 4个类。为什么我得到应用程序委托和其他类的UIViewController类的警告。为什么我必须释放其他类的对象,如果单独的线程给我内存错误?我在这里做错了什么?我不能使用ARC,因为我已经将它与旧的代码整合在一起,这不是使用ARC,我尝试启用ARC类明智的,但它的工作。任何人都可以帮助我找出这个代码中是否有任何内存泄漏。建议是欢迎和appreciated.Thanks提前..

回答

1

两个东西 - 第一次,我看到:

NSString *AsyncRequest = [[NSString alloc] init]; 
AsyncRequest = [vdb SelectAsyncRequest: i : _outgoingMsgId]; 

这应合并到这一点:

NSString *asyncRequest = [vdb SelectAsyncRequest: i : _outgoingMsgId]; 

你,而不是创建一个新实例,然后立即生成或引用另一个实例。

二:

你的代码是非常难以阅读,不遵循Objective-C的Smalltalk的约定。

变量名应以lowercase开头。方法名称也应以小写字母开头。类名和函数应该以大写字母开头。它使阅读变得困难,因为我和其他许多人已经接受过大写字母的训练,并且认为CLASS NAME而不是POSSIBLE VARIABLE NAME。只是供参考

最后,您的一些方法采取多个参数,如上面的一个。你应该为每个参数添加一个前缀,以便很容易理解该参数的用途。这:

[vdb SelectAsyncRequest: PARAMETER : PARAMETER]; 

看起来更好,如果它是:

[vdb selectAsyncRequestForParameter: PARAMETER withOtherParameter:OTHERPARAM]; 

编辑:我也不认为你需要这么多的自动释放池。整个事情已经包装在一个大的autorelease池中。

编辑2:我也看到很多release调用是没有必要的。在您的UploadChunkWise方法中,您正在调用*data*returnedData上的版本,这两个版本均已隐式自动发布,均为。返回对象给你的方法已经被放弃并“移交”给你。当你得到它,如果你想保持它,你将不得不retain它自己

NSData *data = [[NSData alloc] init]; 
return [data autorelease]; 

,否则它会在你的方法的返回值被破坏:从本质上讲,这些方法会做到这一点。

但是,它是正确的,你打电话给你用-init创建的NSString *result实例释放。