什么会导致"Virtual Memory exhausted"错误?



好的。。事情是这样的。。我正在构建一个应用程序,当用户点击下载按钮时,它会下载一堆图像(确切地说是296)。

在模拟器中,一切都完美无瑕,在我的iPhone(4S)上,大约第100张图像出现错误:

malloc:*mach_vm_map(size="某个随机数")失败(错误代码=3)*错误:无法分配区域

libBacktraceRecording.dylib:allocate_free_list_pages()--虚拟内存耗尽!

这是我为下载这些图像而写的代码:

-(void)getData
{
    NSError *error;
    int i;
    NSArray *brojLinije = [[NSArray alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"linije" ofType:@"plist"]];
    NSArray *urlSlike = [[NSArray alloc] initWithContentsOfFile:[[NSBundle mainBundle]pathForResource:@"urlSlike" ofType:@"plist"]];
    NSArray *pocetno = [[NSArray alloc] initWithContentsOfFile:[[NSBundle mainBundle]pathForResource:@"pocetno" ofType:@"plist"]];
    NSArray *sortiranje = [[NSArray alloc] initWithContentsOfFile:[[NSBundle mainBundle]pathForResource:@"sort" ofType:@"plist"]];
    NSArray*paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *desktopDir = [paths firstObject];
    UIImage *image1 = [[UIImage alloc] init];
    for (i = 0; i<296; i++) {
        NSString *brojLinije1 = [NSString stringWithFormat:@"%@",[brojLinije objectAtIndex:i]];
        NSString *pocetno1 = [NSString stringWithFormat: @"%@", [pocetno objectAtIndex:i]];
        NSString *tableSort = [NSString stringWithFormat: @"%@", [sortiranje objectAtIndex:i]];
        image1 = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat: @"http://www.busevi.com/images/stories/Red-Voznje/Gradski-Prevoz-BG/linija.%@.png", [urlSlike objectAtIndex:i ] ]]]];
        NSData *data1 = [NSData dataWithData:UIImageJPEGRepresentation(image1, 0.1)];
        NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
        NSEntityDescription *entity = [[self.fetchedResultsController fetchRequest] entity];
        NSManagedObject *newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:context];
        NSString *pngFilePath = [NSString stringWithFormat:@"%@%@.jpg",desktopDir,[urlSlike objectAtIndex:i]];
        [data1 writeToFile:pngFilePath atomically:YES];
        [newManagedObject setValue:brojLinije1 forKey:@"brojLinije"];
        [newManagedObject setValue:data1 forKey:@"imageData"];
        [newManagedObject setValue:pocetno1 forKey:@"pocetnoStajaliste"];
        [newManagedObject setValue:tableSort forKey:@"sort"];
        NSLog(@"%d / 296", i);
    }
    [self.managedObjectContext save:&error];
}

我唯一知道的是,图像分配频率(分配太多,没有时间自动释放)造成了问题,到目前为止,我已经尝试了我所知道的每一种方法,我看了很多"仪器"应用程序教程,只有一个教程帮助了我(找到填充虚拟内存的来源),但我仍然无法解决我的问题。

您可以在循环内部使用本地自动释放池来立即释放在循环主体中创建的任何对象。

for (i = 0; i<296; i++) {
    @autoreleasepool {
        // loop body goes here...
    }
}

在使用SDWebImage框架时,我遇到了很多来自应用程序的错误和未回答的崩溃。如果即将下载的图像数量低于50张,那么SDWebImage就太棒了。因为,当下载TableViewCell+快速滚动(快速轻弹)中显示的逐张图像时,应用程序在TableView仍在滚动时会收到几次内存警告(SDWebImage只有在TableView缓慢滚动或根本不滚动时才会清除内存),因此会使应用程序崩溃。

因此,在下载300多张图片时,我对应用程序崩溃的唯一安慰是苹果公司的dispatch_async方法。点击此处了解更多信息。

这就是我解决问题的方法(我只需要将所有内容从原来的-(void)getdata方法移动到dispatch_async块。完成!现在看起来是这样的:

-(void)getData {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"Downloading Started");
        slike = [[NSArray alloc]initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"slike" ofType: @"plist"]];
        brojevi = [[NSArray alloc]initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"linije" ofType:@"plist"]];
        pocetnaStajalista = [[NSArray alloc]initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"pocetno" ofType:@"plist"]];
        sort = [[NSArray alloc]initWithContentsOfFile:[[NSBundle mainBundle]pathForResource:@"sort" ofType:@"plist"]];
        NSEntityDescription *entity = [NSEntityDescription entityForName:@"Linija" inManagedObjectContext:self.managedObjectContext];
        NSString *brojLinije;
        NSString *pocetnoStajaliste;
        NSString *sortiranje;
        NSData *data;
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString  *documentsDirectory = [paths objectAtIndex:0];
        NSString  *filePath = [NSString stringWithFormat:@"%@/%@", documentsDirectory,@"filename.png"];
        for (int i = 0; i<314; i++) {
            NSManagedObject *novaLinija = [[NSManagedObject alloc]initWithEntity:entity insertIntoManagedObjectContext:self.managedObjectContext];
            brojLinije = [NSString stringWithFormat:@"%@",brojevi[i]];
            pocetnoStajaliste = [NSString stringWithFormat:@"%@",pocetnaStajalista[i]];
            data = [NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat: @"http://www.busevi.com/images/stories/Red-Voznje/Gradski-Prevoz-BG/linija.%@.png",slike[i]]]];
            [data writeToFile:filePath atomically:YES];
            sortiranje = [NSString stringWithFormat: @"%@", sort[i]];
            [novaLinija setValue:data forKey:@"slikaLinije" ];
            [novaLinija setValue:brojLinije forKey:@"brojLinije"];
            [novaLinija setValue:pocetnoStajaliste forKey:@"pocetnoStajaliste"];
            [novaLinija setValue:sortiranje forKey: @"sort"];
            NSLog(@"%d / 314", i+1);
            NSError *error;
            [self.managedObjectContext save:&error];
        } }

希望这能帮助其他有同样问题的人。祝你好运,编码快乐!

使用了您和我的所有建议和可能的解决方案,但很抱歉,没有一个奏效。

在这种情况下,当应用程序需要下载大量照片时,您真的应该使用SDWebImageDownloader类参考。

我知道改变整个方法并意识到以前的方法(下载照片)是无用的是令人沮丧的,所以这里是关于如何使用SDWebImageDownloader类的教程和示例。祝你好运

相关内容

最新更新