I want a mutable array and set it by a property, which alternate is preferable and please explain the reason. I have the 2 alternatives
NSMutab开发者_Go百科leArray *arrSubTitles_temp = [[NSMutableArray alloc] initWithObjects:
@"String 1",
@"String 2",nil];
self.arrSubTitles = arrSubTitles_temp;
[arrSubTitles_temp release];
OR
NSArray *arrSubTitles_temp = [[NSArray alloc] initWithObjects:
@"String 1",
@"String 2",nil];
self.arrSubTitles = [arrSubTitles_temp mutableCopy];
[arrSubTitles_temp release];
I guess the 1st one is better, as self.arrSubTitles property is retained in .h, so (in 2nd) mutableCopy method will provide the mutable array, but also the retain count will be 2 in this case.
Which method is preferable, should I use retain in .h while setting the property or just assign. Please suggest.
Many thanks in advance :)
- Use
retain
as your property attribute, unless you have a good reason not to (ex:retain
would cause a retain cycle, it's a primitive, you need to guarantee the object is immutable, etc) - Use the first example you posted, since the second one would leak memory.
If you use assign
as your property attribute, then the first option would probably crash:
- Allocate an array (owned by you)
- Assigned to a property (still owned by you)
- Release (no owners, promptly deallocated)
- Attempt to access property value: crash (because the pointer is stale)
The second one, however, would work:
- Allocate an array (+1 owners)
- Copy the array (original: +1 owners, copy: +1 owners)
- Assign the copy into the property (both still have +1 owners)
- Release the original array (it gets deallocated, the copy continues to exist)
Regardless, it is rather unconventional to have an assign
property and then manage the retention of the value yourself. It is extremely error-prone, and much simpler to declare the property as retain
and let the generated setter take care of the release
/retain
dance for you.
Either way is problematic because the caller must provide a mutable array. If the caller ever passes an immutable array (as anything that uses KVC to set the property would be able to do without a compiler warning), you will find yourself holding an immutable array in a mutable-array property, and will shortly thereafter try to mutate it, causing an exception.
What I do is hold a mutable array, which I create in init
and release in dealloc
, as the value of the property, declare the property as @property(nonatomic, copy) NSArray *myArray
, and implement setMyArray:
to send a setArray:
message to my mutable array. At no point do I ever switch out the array; I exclusively and privately own the same mutable array for the entire lifetime of my object.
An equivalent implementation of setMyArray:
would release the array and set the myArray
variable to a mutableCopy
of the input array. The only difference is that this would create and throw away more arrays over the duration of the process.
With either of these solutions, the caller does not need to worry about whether it passes a mutable or immutable array; the property will always do the right thing. And the caller would, as usual, not need to retain it on my behalf.
Note that a setter implementation generated by @synthesize
will not do the right thing. It sends copy
to the input array, which will return an immutable copy. This would be even worse, as then it would not work even if the caller does pass in a mutable array. You must implement a custom setMyArray:
accessor to correctly handle both immutable and mutable arrays.
What about the setting it as autorelease
NSMutableArray *arrSubTitles_temp = [[[NSMutableArray alloc] initWithObjects:
@"String 1",
@"String 2",nil] autorelease];
self.arrSubTitles = arrSubTitles_temp;
[arrSubTitles_temp release];
精彩评论