Instance variables with underscore in Objective-C 2.0 and renaming with @synthetize leads to optimization warnings by the 'Analyze' tool of Xcode 4 [duplicate]

Possible Duplicate:
How does an underscore in front of a variable in a cocoa objective-c class work?

I'm using the same convention for instance variable and properties naming as shown by sebnow in his following answer:

instance variable/ method argument naming in Objective C

I copy paste his example code here:

@interface Foo : NSObject {
    id _bar;
}
@property (nonatomic, retain) id bar;

- (id) initWithBar:(id)aBar;

@end

@implementation Foo
@synthesize bar = _bar;

- (id) initWithBar:(id)aBar {
    self = [super init];
    if(self != nil) {
        _bar = aBar;
    }
    return self;
}

@end

In the implementation of some methods of the Foo class, I use for example:

_bar = aBar

instead of using:

bar = aBar

The 'Analyse' tool introduced by Xcode 4 gives me this warning (I'm using version 4.0.2):

Instance variable 'bar' in class 'Foo' is never used by the methods in its @implementation (although it may be used by category methods)

Perhaps I should use:

self.bar = aBar

But for the readonly properties, that can't work, and beside that, I'm not sure if using the setter in the class itself is a good practice or not.

I'm not fresh in Objective-C, but I'm still in the beginning of learning. Perhaps I'm doing something wrong, and have a bad coding practice somewhere.

Thanks you in advance if you can help me ;)


Solution 1:

"Is never used" should be taken literally: you only define its value in assignments, never use it.

This is the same kind of warning you get for local variables: if you only define their values and never use it, what are they for?

The static analyzer is thus warning you, because typically variables that are never accessed are just remains of older code that has changed and you can remove them. But in your case it could be perfectly fine.

Solution 2:

The @synthesize line affects how the setter and getter for the property 'bar' operate. The line:

@synthesize bar = _bar;

Effectively says "put in the standard getter (and setter, if relevant) for bar, as per the way I've declared it as a @property, but use the instance variable _bar for the storage".

When you use self.bar as an lvalue you're actually making a method call to [self setBar:] and when you use it as an rvalue you're actually making a call to [self bar]. It looks like a normal C-style struct member access but internally it's a method call.

So, the @synthesize creates a suitable getter and setter to use for self.bar, but doesn't change the name of the instance variable. You should therefore be right to use _bar when accessing the thing directly from within the class itself (though some people now frown upon that from a style point of view) and self.bar otherwise, without receiving any analyser warnings.

For you to end up with an instance variable called bar, assuming you didn't declare one inside your interface, the most likely mistake is an error in the way you've performed your @synthesize. In the modern runtime you can supply a @property/@synthesize pair for a variable you haven't actually declared in your interface and the variable will be magically added to your interface. So you can do that by accident if you make an unfortunate typo.

If possible, could you post your actual code?