What's the best way to handle the following situation: You have an NSMutableArray property in your controller class. In viewDidLoad(), you load it up with newly-allocated objects. Then later on, you swap out an object for a new one. Something like:
The way I got it to work was to use autoreleases anytime I declared a new object, like MyObject *object = [[[MyObject alloc] init] autorelease];, but Instruments says I have a leak.
Also, I tried doing it the following way, and I get EXC_BAD_ACCESS, but I don't understand why:
Arrays retain objects added to them and release removed ones. So the first batch looks ok if you were to add autorelease calls to both alloc/inits, or if you called release on object and newObject after you add them to the array.
In a managed memory environment, an object receives a retain message when it’s added; in a garbage collected environment, it is strongly referenced. When an array is deallocated in a managed memory environment, each element is sent a release message.
In a managed memory environment, when an object is removed from a mutable array it receives a release message. If that object is owned only by that array, the object is deallocated when it is removed. If you want to use the object after its removal, you should therefore typically send it a retain message before it’s removed from the array.
What's the best way to handle the following situation: You have an NSMutableArray property in your controller class. In viewDidLoad(), you load it up with newly-allocated objects. Then later on, you swap out an object for a new one. Something like:
The way I got it to work was to use autoreleases anytime I declared a new object, like MyObject *object = [[[MyObject alloc] init] autorelease];, but Instruments says I have a leak.
Also, I tried doing it the following way, and I get EXC_BAD_ACCESS, but I don't understand why:
As Baya said, arrays retain objects that are added to them, and release objects when they are removed. So if you add an autoreleased object to an array, it sticks around as long as it is in the array, and gets released as soon as you remove it from the array.
Your first block of code was creating objects with alloc/init. Objects created with alloc/init have a retain count of 1, and it is your job to release them when you are done with them. You then add them to your array, which causes them to have a retain count of 2. When you remove them from the array, their retain count drops to 1, so they don't get deallocated.
I'm not sure why your second try is crashing, but what you are doing is a band-aid to fix the original problem.
Check out this password generator app that shows various techniques including using a data container singleton object to share data between objects in your project.
Well, I actually got both ways working, so it must have been something else that was causing the EXC_BAD_ACCESS. But I have another question. Say the MyObject class has an object as one of it's properties, something like:
After the object is loaded into the array, object and object.imageView both have a retain count of 2. When dealloc is called, the for loop decrements object to 1, but object.imageView is still at 2. Then when the array releases, object goes to 0 and the MyObject dealloc method gets called taking object.imageView down to 1, not 0. What's the solution?
1. Define a retainer property for your imageView in the header file. @property (nonatomic, retain) UIImageView *imageView;
2. In viewDidLoad you need to release (or autorelease) the new MyObject and UIImageView or you will be leaking them both.
3. Again, you do not need to loop and release objects in an array. When you send release to an array it will automatically send release to each of its objects.