我不喜欢经常问一个问题,但这次没找到问题的解决方案所以我不得不问你如何解决我的问题。
我创建了一个对象 OffLineModeBrain ,用于在应用程序正常工作时下载大量背景图像,我制作代码,一切正常我只是内存有问题,我已经尝试在每个解决方案中按时间释放它但没有结果。 基本上在我的 OffLineModeBrain 中,我有一个方法来执行此操作并加载一个渐进条,这是代码:
-(void)downloadAndSaveByArray:(NSArray *)array{
//PATH
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains( NSCachesDirectory,
NSUserDomainMask, YES);
NSString *cachesDirectory = [paths objectAtIndex:0];
NSString *cachesImageFolderPath = [cachesDirectory stringByAppendingPathComponent:@"com.hackemist.SDWebImageCache.default"];
dispatch_queue_t queueImages = dispatch_queue_create("Images", NULL);
dispatch_queue_t queueDownload = dispatch_queue_create("Download", NULL);
//dispatch_queue_t queueStore = dispatch_queue_create("Store", NULL);
int total = array.count;
__block int progess = 0;
__weak OffLineModeBrain *wself = self;
dispatch_sync(queueImages, ^{
for ( NSString *image in array) {
if (_stop) {
//
NSLog(@"stop");
_stop = NO;
_downloading = NO;
break;
}else{
//CHECK IMAGE IN LOCAL
BOOL success = [fileManager fileExistsAtPath:
[cachesImageFolderPath stringByAppendingPathComponent:
[NSString stringWithFormat:@"/%@", [[image MD5String] lowercaseString]]]];
if (!success) {
dispatch_sync(queueDownload, ^{
if (!_stop) {
//DOWNLOAD AND SAVE
NSError *error;
NSURL *url = [NSURL URLWithString:image];
_urlData = [NSData dataWithContentsOfURL:url] ;
NSLog(@"Download");
if (_urlData)
{
//dispatch_sync(queueStore, ^{
NSString *filePath = [NSString stringWithFormat:@"%@/%@", cachesImageFolderPath, [image MD5String]];
[_urlData writeToFile:filePath atomically:NO];
NSLog(@"Stored");
//RETURN PROGRESS
progess = progess + 1;
[wself.delegate downloadImagesProgress:progess ofTotal:total];
//});
}else{
NSLog(@"Download Images erroe: %@", error);
//RETURN PROGRESS
progess = progess + 1;
[wself.delegate downloadImagesProgress:progess ofTotal:total];
}
//dsf
}else{
NSLog(@"stop");
progess = progess + 1;
if (progess == total) {
_stop = NO;
}
_downloading = NO;
}
});
}else{
NSLog(@"Local");
//RETURN PROGRESS
progess = progess + 1;
[wself.delegate downloadImagesProgress:progess ofTotal:total];
}
}
}//FOR IMAGES ENDED
});
}
这是downloadImagesProgress: ofTotal:
每次更新加载栏的方法。问题开始时,我开始逐个下载图像,然后他们没有释放,仍然在堆中直到结束循环,如果在结束之前停止循环它们也是释放,问题是当循环运行它们在下载和存储后,我没有发布并仍在堆中,我在仪器中看到的是 CFData(存储)每次都会成长,并且会在循环结束时释放。
答案 0 :(得分:0)
我猜,声明
_urlData = [NSData dataWithContentsOfURL:url] ;
将返回“自动释放”对象。
这会产生以下后果:
由于您没有在内部循环中使用自动释放池,因此您可以有效地“保留”自动释放池中的所有返回数据对象,该池在外部内部循环中耗尽。
为了缓解这个问题,简单地在循环中放置一个自动释放池,以便释放dataWithContentsOfURL:
中返回的对象,同时保留内循环的自动释放池的范围:
for (...) {
@autoreleasepool {
...
NSData* data = [NSData dataWithContentsOfURL:url];
...
}
}
虽然使用自动释放池可能有助于解决此问题,但老实说,您还应该检查并重新实现当前的方法。例如,使用dispatch_sync()的方式没有意义。
如果您使用NSURLConnection
的异步方便方法 - 或者甚至更好地使用委托方法,您还可以大大改进您的代码。 (我这样说,尽管我知道异步启动异步任务列表并不容易,除非你对异步模式有很多经验。)