On 7 Apr 2014, at 10:35 am, Varun Chandramohan <varun.chandramo...@wontok.com> 
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 (Cocoa-dev@lists.apple.com)

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to