2011-01-25 4 views
2

J'ai quelques, plein écran, UIColor PatternImages (en scrollViews) dans mon application iPad et je rencontre quelques problèmes de mémoire (surprise?)
Quand je commencé à avoir des problèmes de mémoire, je mis en œuvre le chargement paresseux dans mes scrollviews.
Lorsque les problèmes ont continué, je me suis déplacé loin des méthodes d'usine (comme [UIColor colorWithPatternImage:...]) à « alloc » méthodes ed (comme [[UIColor alloc]initWithPatternImage:...]), pour que je puisse répondre aux avertissements de mémoire en libérant les pages. Cependant, chaque fois que je publie mon UIColor PatternImages, j'obtiens une erreur “EXC_BAD_ACCESS”.manière correcte de libérer un UIColor PatternImage

Au début, je pensais que cela pouvait être causé par mes images de modèle [UIImage imageNamed:...], donc je suis passé à [[UIImage alloc]initWithContentsOfFile:...] images, mais cela n'a pas aidé. Tout à l'heure, je mets NSZombiesEnabled et il me dit que le problème est:

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

Avec le backtrace:

#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... 

Je n'ai aucun UICGColor objets non plus, donc je pense que d'une certaine manière mon "alloc" ed UIColors ont sous-jacents UICGColor autorelease objets ...? Des idées/points de vue?

+2

Concernant votre dernière section de code, bien sûr vous ne devez pas libérer le 'CGImage' parce que vous ne possédez pas le propre (vous n'avez pas appelé' create', 'new' ou' retain'). Vous devriez probablement lire les guides de gestion de la mémoire (pour Cocoa _and_ Core Foundation à nouveau). –

+0

Oh bien sûr - négligent. Je vais supprimer cette partie de la question. Merci. Une idée sur le reste? OK, guide de lecture maintenant ... – iPadDeveloper2011

+0

Après avoir lu quelques-uns des guides mm maintenant (merci @Ole), je crois que cela ne devrait pas avoir d'importance si la patternImage est fabriquée ou allouée. InitWithPatternImage devrait commencer par conserver le UIImage, et c'est la retenue qui est libérée dans UIColor dealloc. – iPadDeveloper2011

Répondre

2

OK, j'ai travaillé sur quelque chose, merci en partie à la question/réponses (mal étiquetées et intitulées) SO here. Ce que j'avais besoin de faire était de lire environ UIView.backgroundColor. Dans mes documents, il est écrit @property(nonatomic, copy) UIColor *backgroundColor.La « copie » ici me dit que quand je dis quelque chose comme:

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

Le myUIView.backgroundColor est en fait un objet différent de [[UIColor alloc]initWithPatternImage:myUIImage]. Cette pièce distincte est, en fait, auto-libérée, donc quand je vais [myUIView.backgroundColor release]; je suis en train de me tirer dans le pied. Ce que je dois faire est:

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

(et bien sûr, autour de cela, je suis aussi allocing et la libération myUIImage). Maintenant pour libérer mon scrollView patternImage, je peux juste faire quelque chose comme currentPage.backgroundColor=nil; (comme @BuildSucceeded) ou currentPage.backgroundColor=[UIColor clearColor]; (pas sûr s'il y a une différence pratique). Je suppose que, en interne, ces deux causes currentPage à autorelease le vieux backgroundColor. Depuis que j'ai effectué ces changements, je n'ai pas réussi à faire planter mon application.

Je dois dire ceci: je ne pense pas que C++ le fasse tout à fait juste, mais C# et Java tous les deux gèrent assez bien sans aucune de cette libération compliquée, autorelease, affaires de @property. Bien sûr, si quelqu'un voulait implémenter un système de gestion de pointeurs analogue (à Objective-C) en Java ou C#, ils le pourraient, mais bien sûr, personne ne le veut parce que ce serait inutile. Pleeeease Apple, migrez loin d'Objective-C!

3

Moi aussi j'avais le même problème et c'est ainsi que j'ai optimisé mon code. Après une analyse dans Instruments et le débogage, j'ai découvert que le pattern colorwith occupera 1,12 mb avec une bibliothèque responsable appelée ripl_create. Pour chaque écran avec colorWithPattern occupera le même 1.12 et ainsi vous aurez des multiples de 1.12 mb alloués. Cela a aspiré mon application. J'ai donc décidé de ne pas colorWithPattern. Je suppose que vous voulez définir l'image à l'arrière-plan d'une vue. Ce que je suggère est de garder un ImageView et placez l'image à elle ...

Venons-en maintenant à l'optimisation de imageView

Si vous voulez que l'image à utiliser dans de nombreuses régions de l'application ou la vue qui contient les l'image sera fréquemment visitée, puis aller pour imagenamed. ImageNamed mettra en cache l'image et ne la publiera pas même si vous la supprimez ou la relâchez.

autre cas où vous wwant image pour être libéré

En vous viewWillAppear ou viewDidLoad affecter l'image à imageView

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

inyour viewDidDisappear fixé nul pour libérer l'image

 imageView.image=nil; 
+0

Hi BuildSucceeded. Quelques commentaires à faire ici. Tout d'abord, oui, j'ai commencé avec beaucoup d'images 1024x768. Je les ai cassés dans _much_ plus petit patternImages parce que je voulais réduire la taille de mon binaire. C'est quand mes problèmes de mémoire ont commencé! En regardant mes images originales, leur taille varie d'environ 100 Ko à 1 Mo, donc 1,12 Mo serait bien pire. – iPadDeveloper2011

+0

Désolé l'homme .. j'ai dit ces détails pour l'iPhone .. Pour l'iPad, je pense qu'il faudra plus de taille de la mémoire, je pense .. iOS ne prend pas la mémoire en fonction de la taille de l'image. Par exemple, si vous avez une image pour 320x480 imageView, il faudra 4 octets pour un pixel. donc il va allouer 320x480x4 = 600kb pour cette image imageView .. – iPrabu

+0

J'ai beaucoup lu récemment sur imageNamed. À mon humble avis, si je veux réutiliser une image, je peux mettre l'UIImage dans ma classe @interface. Je ne comprends pas encore très bien le fonctionnement de votre code, et je suis nerveux lorsque les gens disent des choses comme «ne rien faire». Vous n'effectuez pas le compte de retenue, êtes-vous ...? Je comprends la règle alloc/release. – iPadDeveloper2011

Questions connexes