Загрузка изображений в NSArray с использованием initWithObjects дает сбой, но не с NSMutableArray?

Я выполняю ленивую загрузку изображений в массив после загрузки приложения. Я пробовал использовать NSMutableArray и NSArray (мне не нужно изменять массив после его создания), но последний вылетает у меня.

...
[self performSelectorInBackground:@selector(loadImageArrays) withObject:nil];
...

- (void)loadImageArrays {

    NSAutoreleasePool *pool;
    pool = [[NSAutoreleasePool alloc] init];
    NSString *fileName; 

    imageArray = [[NSMutableArray alloc] init];
    for(int i = 0; i <= x; i++) {
        fileName = [NSString stringWithFormat:@"image_0000%d.png", i];
        [imageArray addObject:[UIImage imageNamed:fileName]];
    }
    [pool drain];
}

vs

NSAutoreleasePool *pool;
pool = [[NSAutoreleasePool alloc] init];
imageArray = [[NSArray alloc] initWithObjects:
            [UIImage imageNamed:@"image_00000.png"],
            [UIImage imageNamed:@"image_00001.png"],
            [UIImage imageNamed:@"image_0000X.png"],
                    nil];
[pool drain];

NSZombieEnabled = YES сообщает мне, что [сохранение UIImage] было отправлено освобожденному экземпляру при использовании последнего фрагмента кода. Оба массива имеют свойство (неатомарное, сохранять) в моем h-файле. Почему изображения не сохраняются в NSArray?


person hwaxxer    schedule 26.01.2010    source источник


Ответы (2)


UIImage является частью UIKit, который не является потокобезопасным. Например, метод imageNamed: может повредить глобальный словарь имя-образ, который класс UIImage использует для кэширования.

Вы должны использовать Core Graphics, если хотите загружать изображения в фоновом потоке.

Изменить, чтобы ответить на ваш комментарий:

Вы можете загружать файлы PNG с помощью:

CGDataProviderRef source = CGDataProviderCreateWithURL((CFURLRef)url);
CGImageRef image = CGImageCreateWithPNGDataProvider(source, NULL, NO, kCGRenderingIntentDefault);
CFRelease(source);

CGImage - это основной фундаментальный объект, который может храниться в NSArray. Затем вы можете сделать из него UIImage (конечно, в основном потоке):

[[UIImage alloc] initWithCGImage:image]
person Nikolai Ruhe    schedule 26.01.2010
comment
Я ценю ответ, но как бы я поступил, если бы хотел использовать Core Graphics для загрузки изображений в фоновом потоке? - person hwaxxer; 26.01.2010
comment
На SO, если ответ приведет вас к большему количеству вопросов, вы должны сделать новый пост. - person Nikolai Ruhe; 26.01.2010
comment
Мне жаль. Однако отличный ответ. Большое спасибо! - person hwaxxer; 26.01.2010
comment
Отлично, я этого не знал ... Ну, по крайней мере, я был прав частично :-) - person Jake; 27.01.2010
comment
Тем не менее, как неизменность и изменчивость связаны с этой проблемой? Или это было просто случайным поведением? - person Jake; 27.01.2010

Хотя я знаю, что существует большая разница между изменяемыми и неизменяемыми массивами, я сам сомневаюсь. Что-то мне подсказывает, что это не просто проблема изменчивости и неизменности. Похоже, ваш бассейн слили преждевременно (звучит противно). Не то чтобы это должно было иметь значение, но не могли бы вы попытаться создать новый поток, выполнив;

[NSThread detachNewThreadSelector:@selector(loadImageArrays) toTarget:self withObject:nil];

Мне просто любопытен результат ... Также попробуйте оба фрагмента в чистой среде (т.е. без другого кода). Если ваш второй фрагмент кода работает там, вам следует поискать решение в другом месте.

person Jake    schedule 26.01.2010