【发布时间】:2015-01-29 08:37:50
【问题描述】:
所以这段代码在 iOS 8 之前对我有用,我已经在 iOS 7.1 的 3000 图像下载循环中对其进行了测试。
但最近我的一些 App 用户向我投诉了 App Crash While Image Download Process。
现在使用这种方式只有 200 张图片正在下载并且应用程序崩溃。
我刚刚发现,每次下载图片时,内存都会增加大约 0.6 到 0.8 MB,并且在大约 200 张图片应用程序崩溃之后。
我必须同步下载图像,因为当我尝试以Background Thread 或Asynchronous mode 下载时,甚至尝试使用dispatch_async(dispatch_get_main_queue() 方式。几秒钟后进程开始,直到那时我使用的 While 循环才到达终点。
所以请在这个问题上帮助我。我该怎么做才能解决它。
我的图片下载代码是:
-(void) downloadImages
{
NSString *myDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
database = [dBName UTF8String];
if (sqlite3_open(database, &dbConnection) == SQLITE_OK)
{
sqliteQuery = [NSString stringWithFormat: @"SELECT ProductID FROM ProductDetails WHERE ImageDownloadStatus = 0"];
int i = 0;
if (sqlite3_prepare_v2(dbConnection, [sqliteQuery UTF8String], -1, &sQLStatement, NULL) == SQLITE_OK)
{
while (sqlite3_step(sQLStatement) == SQLITE_ROW)
{
@autoreleasepool
{
temp = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(sQLStatement, 0)];
NSString *imageURL = [NSString stringWithFormat:@"http://xxxxxxxxxxxxxxx.jpg",clientSite,temp];
myImage = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:imageURL]]];
NSString *imagePath = [NSString stringWithFormat:@"%@/%@.jpg",myDirectory,temp];
NSData *imageData = [NSData dataWithData:UIImageJPEGRepresentation(myImage, 1.0f)];
[imageData writeToFile:imagePath atomically:YES];
sqliteQuery2 = [NSString stringWithFormat: @"UPDATE ProductDetails SET ImageDownloadStatus = 1 WHERE ProductID = \'%@\'",temp];
if (sqlite3_prepare_v2(dbConnection, [sqliteQuery2 UTF8String], -1, &sQLStatement2, NULL) == SQLITE_OK)
{
if (sqlite3_step(sQLStatement2) == SQLITE_DONE)
sqlite3_finalize(sQLStatement2);
}
[self performSelectorInBackground:@selector(updateUILabels) withObject:nil];
i = i + 1;
}
}
sqlite3_finalize(sQLStatement);
}
sqlite3_close(dbConnection);
}
}
-(void) updateUILabels
{
@autoreleasepool
{
progressCounter.hidden = NO;
lblProgressStatus.hidden = NO;
spinner.hidden = NO;
[spinner startAnimating];
lblProgressStatus.text = @"Synchronising Product Images...";
lblProgressCounter.text = [NSString stringWithFormat:@"%d / %d”, i,total];
}
}
【问题讨论】:
-
首先阅读有关 performSelectorInBackground stackoverflow.com/questions/19500820/… 的内容。也永远不要从后台线程更新 UI 元素。
-
@AndreasZ 我只是检查了这个
[self performSelectorOnMainThread:@selector(updateUILabels:) withObject:nil waitUntilDone:NO];,但用户界面没有更新:( -
dowloadImages 是否在后台线程上运行?如果不是简单地调用 [self updateUILabels]。但是,如果您不使用后台线程来下载图片,您将阻塞主线程。
-
@AndreasZ
downloadImages正在主线程上运行。我怎样才能阻塞主线程 -
您应该在后台线程上执行 downloadImages。我在您的问题中写道“我必须同步下载图像,因为当我尝试在后台线程或异步模式下下载甚至尝试使用 dispatch_async(dispatch_get_main_queue() 方式时。进程在几秒钟后开始,直到那时我正在使用的循环只是到达终点。”当您说您正在使用的 while 循环到达终点时,您是什么意思?
标签: ios objective-c iphone memory-management ios8