[英]NSThread Causing memory Leaks in iPhone
我在后台線程中明智地上傳圖像,每個塊的大小為512kb,據我所知,我已經使用release,nsautoreleasepool來處理內存泄漏問題。 以下是分塊上傳圖像的代碼。
- (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次內存警告,然后該應用程序崩潰。在控制台中,我首先在應用程序委托類上獲取內存警告,然后是4個擴展UIViewController的類。 為什么我在應用程序委托和其他類型為UIViewController的類上收到警告。如果單獨的線程給我內存錯誤,為什么我必須釋放其他類的對象? 我在這里做錯了什么? 我無法使用ARC,因為我已將其與不使用ARC的舊代碼集成在一起,因此我嘗試了明智地啟用ARC類,但是這樣做並不起作用。 誰能幫助我找出這段代碼中是否有內存泄漏。 歡迎提出建議並表示贊賞。
兩件事-首先,我看到了這一點:
NSString *AsyncRequest = [[NSString alloc] init];
AsyncRequest = [vdb SelectAsyncRequest: i : _outgoingMsgId];
這應該合並為:
NSString *asyncRequest = [vdb SelectAsyncRequest: i : _outgoingMsgId];
相反,您正在創建一個新實例,然后立即生成或引用另一個實例。
第二:
您的代碼很難閱讀,並且不遵循Objective-C smalltalk約定。
變量名稱應以lowercase
字母開頭。 方法名稱還應該以小寫字母開頭。 類名和功能應以大寫字母開頭。 由於我和許多其他人已經受過訓練,可以看到大寫字母並認為“類別名稱”而不是“可能的變量名稱”,因此很難閱讀。 僅供參考
最后,您的某些方法采用多個參數,例如上面的參數。 您確實應該為每個參數添加一個前綴,以便於理解該參數的用途。 這個:
[vdb SelectAsyncRequest: PARAMETER : PARAMETER];
如果是,它將看起來更好:
[vdb selectAsyncRequestForParameter: PARAMETER withOtherParameter:OTHERPARAM];
編輯:我也不認為您需要那么多自動發布池。 整個內容已經包裝在一個大型自動釋放池中。
EDIT2:我還看到了很多不必要的release
調用。 在您的UploadChunkWise
方法中,您要對*data
和*returnedData
調用release,它們已經隱式自動釋放 。 將對象返回給您的方法將已經擁有所有權並“移交給”您。 本質上,這些方法可以做到這一點:
NSData *data = [[NSData alloc] init];
return [data autorelease];
當您獲取它時,如果要保留它,則必須自己retain
它,否則它將在方法返回時銷毀。
但是,對使用-init
創建的NSString *result
實例調用release是正確的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.