Automatic iVars with @synthesize
Asked Answered
M

3

6

I understand that starting with iOS 4, there is now the ability to not declare iVars at all, and allow the compiler to automatically create them for you when you synthesize the property. However, I cannot find any documentation from Apple on this feature.

Also, is there any documentation on best practices or Apple recommended guidelines on using iVars and properties? I have always use properties like this:

.h file

@interface myClass {
    NSIndexPath *_indexPath
}

@property(nonatomic, retain) NSIndexPath *indexPath

@end

.m file

@implementation myClass

@synthesize indexPath = _indexPath;

- (void)dealloc {
    [_indexPath release];
}
@end

I use the _indexPath instead of indexPath as my iVar name to make sure that I don't ever use indexPath when I need to use self.indexPath. But now that iOS supports automatic properties, I don't need to worry about that. However, if I leave out the iVar declaration, how should I handle releasing it in my dealloc? I was taught to use iVars directly when releasing in dealloc, rather than using the property methods. If I don't have an iVar at design-time, can I just call the property method instead?

Marcello answered 17/3, 2011 at 18:23 Comment(0)
C
6

I've went through many different ways of dealing with this. My current method is to use the property access in dealloc. The reasons not to are too contrived (in my mind) to not do it, except in cases where I know the property has odd behavior.

@interface Class
@property (nonatomic, retain) id prop;
@end

@implementation Class
@synthesize prop;

- (void)dealloc;
{
    self.prop = nil;
    //[prop release], prop=nil; works as well, even without doing an explicit iVar
    [super dealloc];
}
@end
Cenacle answered 17/3, 2011 at 18:59 Comment(0)
C
5

In constrast, I do the following:

@interface SomeViewController : UIViewController

@property (nonatomic, copy) NSString *someString;

@end

and then

@implementation SomeViewController

@synthesize someString;

- (void)dealloc
{
    [someString release], someString = nil;
    self.someString = nil; // Needed?

    [super dealloc];
}

@end

Note: At some point Apple will enable synthesize-by-default which will no longer require the @synthesize directive.

Chinoiserie answered 17/3, 2011 at 18:59 Comment(5)
You can access someString directly that way, even when you haven't declared a someString iVar? I thought the iVar wouldn't get created until compilation. Also, how does the comma work? Why isn't that a semicolon?Marcello
synthesize-by-default was a buggy mess when it was in there, but it can't come back soon enough.Cenacle
@Gendolkari Yes, you can access the synthesized ivars in code just fine. The compiler is smart enough to know they'll be there eventually. You can even modify the name of the synthesized iVar using the '@synthesize obj = _myName' without explicitly declaring _myName anywhere. As for the comma operator its a standard C thing, it evaluates each expression, left to right. And the value of the 'comma expression' is the value of the right side.Cenacle
Thanks! So the only possible reason I can think of to use a different name for my iVar is still to help avoid accidentally leaving off the self. and accessing the iVar directly when I don't want to... is this a valid concern?Marcello
I used to think it was, but decided that it doesn't matter most of the time, and I never access raw iVars anyway outside of the overridden properties.Cenacle
R
3

You can directly access instance variables using -> symbol instead of dot . (which will invoke ivar's corresponding accessor method):

.h

@interface myClass {
}
@property(nonatomic, retain) NSIndexPath *indexPath

@end

.m

@implementation myClass

- (void)dealloc {
    [self->indexPath release];
    self->indexPath = nil; // optional, if you need it

    [super dealloc];
}
@end

Thus you will directly access iVar and not it's corresponding accessor method, obtaining additional benefit - performance.

Richter answered 17/3, 2011 at 18:41 Comment(10)
There are number of issues in it, maybe a downvote wasn't the best way to handle it (And has now been backed out). Recommending to use self-> is an odd choice here, and completely unnesary. Also _ is not reserved by Apple for variable names, only for method names. That doesn't change that its 'bad' style though (that is obviously opinion). As an aside __ is reserved by the compiler.Cenacle
Ok, I found information about how you can access an iVar with either self->iVar or just iVar by itself. But in this case, that iVar doesn't exist until compilation time, so can you do that?Marcello
-> approach is used often in official Apple's code snippets. _ symbol is reserved for instance variablesRichter
Apple's code snippets don't follow a common coding style, they're all over the board. And where do they state that _ is reserved?Cenacle
@Marcello yes, you can do that. Just testedRichter
@Joshua please, consult this one #3544567Richter
@Martin, that seems to agree with me.Cenacle
@Joshua ok, regarding underscore you're right. But affirmations about -> approach being odd choice and completely unnecessary are not quite good arguments. In the following project example you can find this symbol everywhere and especially in dealloc method: developer.apple.com/library/ios/#samplecode/…Richter
@Martin, Its odd because its unnecessary to the meaning of the expresion. If anything I find it more confusing because now you're relying on the operator to tell the difference between two VERY different operations that look similar. It just adds line noise. It is purely a style/opinion issue of course. But showing Apple sample-code is unhelpful; as I stated previously, they have no guiding style between their samples.Cenacle
@Joshua: line noise for you maybe. For me prop = nil is a noise too, because if something wrong in mem-management occur I want my program to crash instead of running abnormally in silence. What I've proposed is not something wrong, the only issue is - it's not up to Joshua's style :)Richter

© 2022 - 2024 — McMap. All rights reserved.