Ios 向远程服务器上的存储过程提供同步调用的函数会导致内存警告
我在iOS应用程序的远程服务器上上传包含应用程序中图像文件夹的ZIP。该函数在单独的NSThread中调用,因此它不应阻塞UI。在这里,我创建了一批包含图像(最大10MB)的文件夹,并通过调用远程服务器上的SP将它们上载到远程服务器上。问题是每次调用这个方法都会增加我的活动字节数,这取决于zip文件的大小,而zip文件再也不会下降。下面是我的代码:Ios 向远程服务器上的存储过程提供同步调用的函数会导致内存警告,ios,memory-leaks,base64,nsthread,synchronous,Ios,Memory Leaks,Base64,Nsthread,Synchronous,我在iOS应用程序的远程服务器上上传包含应用程序中图像文件夹的ZIP。该函数在单独的NSThread中调用,因此它不应阻塞UI。在这里,我创建了一批包含图像(最大10MB)的文件夹,并通过调用远程服务器上的SP将它们上载到远程服务器上。问题是每次调用这个方法都会增加我的活动字节数,这取决于zip文件的大小,而zip文件再也不会下降。下面是我的代码: -(IBAction)syncPressed:(id)sender { [[UIApplication sharedApplication] set
-(IBAction)syncPressed:(id)sender
{
[[UIApplication sharedApplication] setIdleTimerDisabled:YES];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *strServerFolderPath = [[paths objectAtIndex:0]stringByAppendingPathComponent:app.objDataAccess.tempServerIPAddress];
NSString *strImagesFolderPath=[strServerFolderPath stringByAppendingPathComponent:@"Images"];
NSString *strDatabaseImagesPath=[strImagesFolderPath stringByAppendingPathComponent:app.objDataAccess.tempDBName];
NSArray *arrOfDirectoryToZip=[[NSFileManager defaultManager] contentsOfDirectoryAtPath:strDatabaseImagesPath error:NULL];
int iZippedFolderCounter=0;
if(app.viewController.arrADataSyncProgress==nil)
app.viewController.arrADataSyncProgress=[[NSMutableArray alloc]init];
else
[app.viewController.arrADataSyncProgress removeAllObjects];
unsigned long long int iSizeOfFolder=[app.globalVcImageViewController folderSize:strDatabaseImagesPath];
int iNoOfBatches=iSizeOfFolder/10485760;
if(iSizeOfFolder%10485760>0)
iNoOfBatches++; //We will need to add one more batch for remainings
int iCounter=1;
//Add batch objects in array initially so that they can be updated at correct time
while(iCounter<=iNoOfBatches)
{
SyncProgress *objSync=[[SyncProgress alloc]init];
objSync.cSyncName=[NSString stringWithFormat:@"Batch %d",iCounter];
objSync.iSyncStatus=0;
objSync.cSpName=@"UploadImageData";
objSync.cStartSyncTime=@" ";
objSync.cEndTime=@" ";
[app.viewController.arrADataSyncProgress addObject:objSync];
objSync=nil;
iCounter++;
}
[app.viewController.tblviwSyncProgress performSelectorInBackground:@selector(reloadData) withObject:nil];
float fPerBatchIncrement=100.0/iNoOfBatches;
[Flurry logEvent:@"Sync started"];
[app.objLogger writetoLogFileWithMessage:@"Sync started" withMethodName:@"syncPressed:" withLoggerLevel:eLoggerInfo];
int iBatchCounter=0;
//Upload images batchwise
while(iBatchCounter<iNoOfBatches)
{
NSMutableArray *arrmPathsToZip=nil;
unsigned long long int iSizeOfBatch=0;
//In each batch 10 MB or remaining folders are zipped
while(iZippedFolderCounter<arrOfDirectoryToZip.count && (iSizeOfBatch+[app.globalVcImageViewController folderSize:[strDatabaseImagesPath stringByAppendingPathComponent:[arrOfDirectoryToZip objectAtIndex:iZippedFolderCounter]]])<10485760 && iZippedFolderCounter<arrOfDirectoryToZip.count)
{
//Add Paths to temporary array
if(arrmPathsToZip==nil)
arrmPathsToZip=[[NSMutableArray alloc]init];
[arrmPathsToZip addObject:[strDatabaseImagesPath stringByAppendingPathComponent:[arrOfDirectoryToZip objectAtIndex:iZippedFolderCounter]]];
iSizeOfBatch+=[app.globalVcImageViewController folderSize:[strDatabaseImagesPath stringByAppendingPathComponent:[arrOfDirectoryToZip objectAtIndex:iZippedFolderCounter]]];
iZippedFolderCounter++;
}
//Give the zip a random unique name
NSString *strRandomFolderName=[NSString stringWithFormat:@"%f",[[NSDate date] timeIntervalSince1970]];
NSString *strZipPath= [strImagesFolderPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.zip",strRandomFolderName]];
//Create zip from the folder
BOOL bSuccess = [SSZipArchive createZipFileAtPath:strZipPath withContentsOfDirectoris:arrmPathsToZip];
arrmPathsToZip=nil;
if(!bSuccess)
{
[app removeCustomLoader];
UIAlertView *altError=[[UIAlertView alloc]initWithTitle:app.strAppName message:@"Error occured while gathering data" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
[altError show];
altError=nil;
}
else
{
//Update sync progress object
SyncProgress *objSyncProgress=(SyncProgress*)[app.viewController.arrADataSyncProgress objectAtIndex:iBatchCounter];
objSyncProgress.cStartSyncTime = [app.loginView getCurrentTimeInUTCFormatToString];
[app.viewController.tblviwSyncProgress performSelectorInBackground:@selector(reloadData) withObject:nil];
NSData *dat=[NSData dataWithContentsOfFile:strZipPath];
//[Base64 initialize];
NSString *strZipEncoded = [Base64 encode:dat];
NSString *cDBToken=app.dbToken;
//Get Key From GUID
NSString *cGUID=[app.loginView generateUuidString];
int iKey = [app.loginView KeyFromGUID:cGUID];
//Encrypt Parameter
cDBToken=[app.loginView encrypt:cDBToken withShiftCount:iKey];
cDBToken= [NSString stringWithFormat:@"%@##%@",cGUID,cDBToken];
NSString *strUserName=[app.loginView encrypt:app.LoginUsrnm withShiftCount:iKey];
NSString *strPassword=[app.loginView encrypt:app.LoginPswd withShiftCount:iKey];
NSString *strSPName=[app.loginView encrypt:@"_wspIICInsertImages" withShiftCount:iKey];
//SOAP Request
NSMutableString *soapMsg =[[NSMutableString alloc] initWithFormat:@"<?xml version=\"1.0\" encoding=\"utf-8\"?>\
<soap:Envelope\
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\
xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\
xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\
<soap:Body>\
<UploadImageData\
xmlns=\"http://tempuri.org/\">\
<DBToken><![CDATA[%@]]></DBToken>\
<UserName><![CDATA[%@]]></UserName>\
<Password><![CDATA[%@]]></Password>\
<DeviceID>1</DeviceID>\
<BatchSize>1</BatchSize>\
<DocString><![CDATA[%@]]></DocString>\
<fileName><![CDATA[%@]]></fileName>\
<SPName><![CDATA[%@]]></SPName>\
</UploadImageData>\
</soap:Body>\
</soap:Envelope>",cDBToken,strUserName,strPassword,strZipEncoded,strRandomFolderName,strSPName];
NSURL *url = [NSURL URLWithString:app.webServiceName];
NSMutableURLRequest *req =
[NSMutableURLRequest requestWithURL:url];
NSString *msgLength =
[NSString stringWithFormat:@"%d", [soapMsg length]];
[req addValue:@"text/xml; charset=utf-8"
forHTTPHeaderField:@"Content-Type"];
[req addValue:msgLength
forHTTPHeaderField:@"Content-Length"];
//add gzip-encoding to HTTP header
[req setValue:@"gzip" forHTTPHeaderField:@"Accept-Encoding"];
[req addValue:@"http://tempuri.org/UploadImageData"
forHTTPHeaderField:@"SOAPAction"];
[req setHTTPMethod:@"POST"];
[req setHTTPBody: [soapMsg dataUsingEncoding:NSUTF8StringEncoding]];
soapMsg=nil;
[req setTimeoutInterval: 60];
//call method to connect to webservice by passing request object
NSURLResponse* urlResponse = nil;
NSError *error;
NSData *responseData = [NSURLConnection sendSynchronousRequest:req returningResponse:&urlResponse error:&error];
NSString *strResponse=[[NSString alloc]initWithData:responseData encoding:NSUTF8StringEncoding];
[[NSFileManager defaultManager] removeItemAtPath:strZipPath error:NULL];
if(iZippedFolderCounter<arrOfDirectoryToZip.count)
app.viewController.fPercentageSync=app.viewController.fPercentageSync+fPerBatchIncrement;
else
app.viewController.fPercentageSync=100;
app.viewController.fDataSize+=dat.length/(1024.0*1024);
dat=nil;
//Update sync progress object
objSyncProgress=(SyncProgress*)[app.viewController.arrADataSyncProgress objectAtIndex:iBatchCounter];
if([[app stringBetweenString:@"<UploadImageDataResult>" andString:@"</UploadImageDataResult>" withstring:strResponse] isEqualToString:@"true"])
{
objSyncProgress.iSyncStatus=1;
}
else
objSyncProgress.iSyncStatus=2;
objSyncProgress.cEndTime=[app.loginView getCurrentTimeInUTCFormatToString];
[app performSelectorInBackground:@selector(setHUDSubtitle:) withObject:[NSNumber numberWithFloat:app.viewController.fPercentageSync]];
[app.viewController.tblviwSyncProgress performSelectorInBackground:@selector(reloadData) withObject:nil];
responseData=nil;
strResponse=nil;
strZipEncoded=nil;
}
iBatchCounter++;
}
btnSync.selected=NO;
[Flurry logEvent:@"Sync completed"];
[app.viewController.actSyncProgress stopAnimating];
[app removeCustomLoader];
NSDateFormatter *formatter=[[NSDateFormatter alloc]init];
formatter.dateFormat=@"dd-MM-yyyy hh:mm:ss a";
NSString *strSyncCompletionDate=[formatter stringFromDate:[NSDate date]];
[app.objDataAccess insertIntoDatabaseUserName:app.LoginUsrnm syncCompletionTime:strSyncCompletionDate dataSize:app.viewController.fDataSize serverName:app.loginView.tempServerName databaseName:app.loginView.tempDBName];
[[UIApplication sharedApplication] setIdleTimerDisabled:NO];
}
任何关于我哪里出了问题的指点都将受到极大的赞赏
编辑:使用工具查看分配后,我注意到它们指向下面屏幕截图中显示的te线:
NSData *responseData = [NSURLConnection sendSynchronousRequest:req returningResponse:&urlResponse error:&error];
我还将我的代码附在@autoreleasepool中
请帮助我,因为我还没有得到如何才能避免这一点
将这些指针设置为nil时,对象仍在内存中:
responseData=nil;
strResponse=nil;
strZipEncoded=nil;
请尝试此操作,并查找其他未释放内存的位置:
[responseData release];
[strResponse release];
[strZipEncoded release];
通过查看来检测泄漏太难了,但我有一个简单的建议可能会有所帮助。用@autorelease{}包围你的代码。试过了。没用!您是否尝试进行heapshot分析,它将帮助您找到泄漏源。感谢大家提供有用的评论。我也做了堆快照分析,检查了分配情况,工具指向了更新问题中显示的代码片段。请帮我解决这个问题。我有最后三点建议。make req=nil;调用后,在收到内存警告时清除url缓存,不要使用sendSynchronousRequest。还有一件事,看看gcd和quees。不用担心,我没有喝咖啡。谢谢你的澄清和道歉。
[responseData release];
[strResponse release];
[strZipEncoded release];