Правильный способ освободить UIColor PatternImage

У меня есть несколько полноэкранных UIColor PatternImagesscrollViews) в приложении iPad, и у меня проблемы с памятью (сюрприз?)
Когда у меня начались проблемы с памятью, я реализовал ленивую загрузку в моих просмотрах прокрутки.
Когда проблемы продолжались, я перешел от фабричных методов (таких как [UIColor colorWithPatternImage:...]) к методам "выделения" (например, [[UIColor alloc]initWithPatternImage:...]), чтобы я мог реагировать на предупреждения памяти, освобождая страницы.

Однако всякий раз, когда я отпускаю свои изображения UIColor PatternImages, я получаю “EXC_BAD_ACCESS” ошибку.

Сначала я подумал, что это может быть вызвано моими [UIImage imageNamed:...] изображениями шаблонов, поэтому я переключился на [[UIImage alloc]initWithContentsOfFile:...] изображений, но это не помогло. Только что я установил NSZombiesEnabled, и он говорит мне, что проблема в следующем:

-[UICGColor release]: message sent to deallocated instance 0x187b50

Со следом:

#0  0x35823910 in ___forwarding___ ()
#1  0x35823860 in __forwarding_prep_0___ ()
#2  0x357e53c8 in CFRelease ()
#3  0x357e48de in _CFAutoreleasePoolPop ()
#4  0x3116532c in NSPopAutoreleasePool ()
#5  0x341a7508 in _wrapRunLoopWithAutoreleasePoolHandler ()
#6  0x3580ac58 in __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ ()
#7  0x3580aacc in __CFRunLoopDoObservers ()
#8  0x358020ca in __CFRunLoopRun ()
#9  0x35801c86 in CFRunLoopRunSpecific ()
#10 0x35801b8e in CFRunLoopRunInMode ()
#11 0x320c84aa in GSEventRunModal ()
#12 0x320c8556 in GSEventRun ()
#13 0x341dc328 in -[UIApplication _run] ()
#14 0x341d9e92 in UIApplicationMain ()
#15 0x00002e5e in main (argc=1, argv=0x2fdff610) at...

У меня тоже нет UICGColor объектов, поэтому я думаю, что каким-то образом мои "выделенные" UIColors объекты имеют базовые UICGColor объекты автозапуска ...? Любые идеи / идеи?


person iPadDeveloper2011    schedule 25.01.2011    source источник
comment
Что касается вашего последнего раздела кода, конечно, вы не должны выпускать CGImage, потому что он вам не принадлежит (вы не называли для него create, new или retain). Вам, вероятно, следует прочитать руководства по управлению памятью (снова для Cocoa и Core Foundation).   -  person Ole Begemann    schedule 25.01.2011
comment
Ну конечно - небрежно. Я удалю эту часть вопроса. Спасибо. Есть идеи по остальному? Хорошо, сейчас читаю руководство ...   -  person iPadDeveloper2011    schedule 25.01.2011
comment
Прочитав некоторые руководства по мм сейчас (спасибо @Ole), я считаю, что не должно иметь значения, является ли patternImage фабричным или выделенным. InitWithPatternImage должен начинаться с сохранения UIImage, и это сохранение, которое освобождается в UIColor dealloc.   -  person iPadDeveloper2011    schedule 25.01.2011
comment
Я только что сбрил еще один вопрос. Пока я говорю по теме, имеет ли значение, являются ли объекты (UIImage), принадлежащие UIColor, фабричными или выделенными? на который я только что ответил в комментарии выше   -  person iPadDeveloper2011    schedule 25.01.2011


Ответы (2)


У меня тоже была такая же проблема, и именно так я оптимизировал свой код.

После некоторого анализа в инструментах и ​​отладки я обнаружил, что colorwith pattern будет занимать 1,12 мб с ответственной библиотекой ripl_create. Для каждого экрана с colorWithPattern будет занимать одно и то же значение 1,12, поэтому у вас будет выделено кратное 1,12 МБ. Это сосало мое приложение, поэтому я решил, что нет colorWithPattern.

Я думаю, вы хотите установить изображение в качестве фона представления. Я бы посоветовал сохранить ImageView и поместить в него изображение ...

Теперь перейдем к оптимизации imageView

Если вы хотите, чтобы изображение использовалось во многих частях приложения или представление, содержащее изображение, будет часто посещаться, тогда выберите imagenamed.

imageNamed кэширует изображение и не освобождает его, даже если вы обнуляете его или освобождаете.

В другом случае, когда вы хотите, чтобы изображение было выпущено

В вашем viewWillAppear или viewDidLoad назначьте изображение для imageview

        NSString *fileLocation = [[NSBundle mainBundle] pathForResource:@"yourImage" ofType:@"png"];
        imageView.image = [UIImage imageWithData:[NSData dataWithContentsOfFile:fileLocation]]; 

inYour viewDidDisappear устанавливает ноль, чтобы освободить изображение

       imageView.image=nil;
person ipraba    schedule 25.01.2011
comment
Привет, BuildSucceeded. Здесь можно сделать несколько замечаний. Во-первых, да, я действительно начал с большого количества изображений 1024x768. Я разбил их на намного более мелкие изображения шаблонов, потому что я хотел уменьшить размер моего двоичного файла. Вот тогда и начались проблемы с памятью! Если посмотреть на мои исходные изображения, их размер варьируется от 100 КБ до 1 МБ, поэтому 1,12 МБ будет намного хуже. - person iPadDeveloper2011; 25.01.2011
comment
Извините, чувак ... Я сказал эти подробности для iPhone ... Думаю, для iPad потребуется больший объем памяти, я думаю ... iOS не занимает память в зависимости от размера изображения. Например, если у вас есть изображение для ImageView размером 320x480, для пикселя потребуется 4 байта. поэтому для этого изображения imageView будет выделено 320x480x4 = 600 КБ .. - person ipraba; 25.01.2011
comment
В последнее время я много читал об imageNamed. IMHO, если я хочу повторно использовать изображение, я могу поместить UIImage в свой класс @interface. Я еще не совсем понимаю, как работает ваш код, и нервничаю, когда люди говорят такие вещи, как set nil to release. Вы не производите счетчик удержания, не так ли ...? Я понимаю правило выделения / освобождения. - person iPadDeveloper2011; 25.01.2011
comment
Значит, iPad требует 1024x768x4 = примерно 3 МБ для отображения полноэкранного изображения? Так что colorWithPattern может быть лучше !? - person iPadDeveloper2011; 25.01.2011
comment
Итак, вы хотите повторно использовать изображение, поэтому теперь используйте imageName без выделения ... не беспокойтесь о nil или release. По моему опыту, я хочу сказать, что colorWithpattern занимает огромный объем памяти, поэтому используйте imageViews там, где вы хотите, чтобы ваше изображение. - person ipraba; 25.01.2011
comment
Думаю, ваш ответ немного не по теме. Если бы я мог просто правильно выпустить свои UIColors, я думаю, все было бы в порядке. Кто-нибудь? - person iPadDeveloper2011; 25.01.2011
comment
Я думаю, что Instruments - ваш лучший друг ... используйте это и найдите то, что занимает больше памяти ... Для меня в iPhone colorWithpattern требуется 1,12 МБ, а imageView - 600 КБ - person ipraba; 25.01.2011
comment
Мммм ... Я использую ImageViews - это просто их bgs по образцу. Вы имеете в виду использование UIImages, а не PatternImages. Ммм ... назад туда, где я был 1 месяц разработки назад! :-( - person iPadDeveloper2011; 25.01.2011
comment
Я в порядке, если PatternImages требует больше памяти - потому что я получаю намного меньший двоичный файл для компенсации. Мне - просто - нужно - освободить - UIColors - правильно! - person iPadDeveloper2011; 25.01.2011
comment
О, возможно, вы имеете в виду мозаику множества UIImageView, каждый с одним и тем же (шаблоном) изображением !? Было бы так безумно, если бы это оказалось лучше, чем использование UIColor patternImages! Это то, что вы имели ввиду? - person iPadDeveloper2011; 25.01.2011

Хорошо, я кое-что придумал, отчасти благодаря (плохо помеченным и названным) вопросам / ответам SO здесь . Мне нужно было прочитать о UIView.backgroundColor. В моих документах написано @property(nonatomic, copy) UIColor *backgroundColor. «Копия» здесь говорит мне, что когда я говорю что-то вроде:

myUIView.backgroundColor=[[UIColor alloc]initWithPatternImage:myUIImage];

myUIView.backgroundColor на самом деле объект, отличный от [[UIColor alloc]initWithPatternImage:myUIImage]. Этот отдельный myUIView.backgroundColor фактически выпускается автоматически, поэтому, когда я иду [myUIView.backgroundColor release];, я фактически стреляю себе в ногу. Что мне нужно сделать:

UIColor* tmpColor=[[UIColor alloc]initWithPatternImage:myUIImage];
currentPage.backgroundColor=tmpColor;
[tmpColor release];

(и, конечно же, в связи с этим я также выделяю и освобождаю myUIImage). Теперь, чтобы выпустить свой scrollView patternImage, я могу просто сделать что-то вроде currentPage.backgroundColor=nil; (например, @BuildSucceeded) или currentPage.backgroundColor=[UIColor clearColor]; (не уверен, есть ли практическая разница). Я полагаю, что внутренне оба эти фактора приводят к currentPage к autorelease старому backgroundColor. После внесения этих изменений я не смог заставить мое приложение аварийно завершить работу.

Я должен сказать следующее: я не думаю, что C ++ делает это правильно, но и C #, и Java прекрасно справляются без какой-либо этой сложной версии, автоматического выпуска, бизнеса @property. Конечно, если бы кто-то хотел реализовать аналогичную (для Objective-C) систему управления указателями на Java или C #, они могли бы это сделать, но, конечно, никому это не нужно, потому что это было бы довольно бесполезно. Pleeeease Apple, откажитесь от Objective-C!

person iPadDeveloper2011    schedule 26.01.2011