Re: Retain count in non ARC
Re: Retain count in non ARC
- Subject: Re: Retain count in non ARC
- From: Graham Cox <email@hidden>
- Date: Mon, 07 Apr 2014 12:18:58 +1000
On 7 Apr 2014, at 10:35 am, Varun Chandramohan <email@hidden> wrote:
> Hi Graham,
>
> Thank you for such detailed explanation. I made a few changes except the
> type check of what NSPropertyListSerialization returns. Ill be adding that
> soon. Other than that, I wanted you to take a look at the changes I made
> and let me know if you see any problems. I tested it, at it seems fine and
> the warnings went away.
>
> @interface TempConfig : NSObject {
> NSMutableArray* ivarContents;
> }
>
OK so far....
> @property (retain) NSArray* contents;
Should be:
@property (copy) NSArray* contents;
given that below the method -setContents actually copies the array you pass to its internal array. In fact it doesn't matter what you put there, since you're writing your own -setContents:, but it's correct to ensure that your public API does actually declare the behaviour it implements, so that client code doesn't get any nasty surprises later.
>
> - (void) setContents:(NSArray *)serializeObj
> {
> if (serializeObj) {
> ivarContents = [serializeObj mutableCopy];
> } else {
> ivarContents = [[NSMutableArray alloc] initWithCapacity:10 ];
> }
> contents = ivarContents;
> }
>
> - (id) contents
> {
> return contents;
> }
This isn't what I meant by backing your 'contents' property with an ivar. This isn't doing that. Instead you now have two ivars, one you've declared yourself and one that's hidden, created by the system, named '_contents'. There's no need for that duplication and potential for them to get out of step.
Instead, do this in your implementation (warning, typed into Mail):
@synthesize contents = ivarContents;
Having done that you'll now only have one ivar, the one you declared, and it will be associated with the property 'contents'. You won't need to write your own getter, but the setter should look something like:
- (void) setContents:(NSArray*) serializeObj
{
NSAssert([serializeObj isKindOfClass:[NSArray class]], @"expected an NSArray here");
if( ivarContents == nil )
ivarContents = [[NSMutableArray alloc] initWithArray:serializeObj]; // assuming not allocated by -init method
else
[ivarContents setArray:serializeObj];
}
> - (void) dealloc
> {
> [ivarContents release]; // <----------- yes
> contents = nil; // <----------- you don't need this
> [super dealloc];
> }
Since you indicate that you have methods to add additional elements to your contents array, it would probably be best to allocate 'ivarContents' in your -init method, so that if -setContents: is never invoked, you still can add those extra elements without having to check if the array needs creating. Then, -setContents reduces even further, to a simple wrapper around -setArray:
(As an aside, the fact that @synthesize is now optional, and hidden ivars are created by the system to back properties you declare in the absence of any other information, there's now a whole new class of bugs waiting to trap the unwary developer, where you think you're dealing with an ivar you've declared, but in fact it's another one, perhaps with a very similar name, that you can't see. This situation produces no warning, no error, but incorrect behaviour. I appreciate the convenience of properties, but this automatic backing feature goes too far and increases bugginess. It's caught me out a few times now).
hope that helps,
--Graham
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden