2013-08-29 76 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實例釋放。