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]

自古美人都是妖i 提交于 2020-01-08 18:01:31

问题


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 ;)


回答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.




回答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?




回答3:


Please see my comment.

Try adding a -dealloc method to release the object. This will 'access' the Ivar and should make the static analyser happy.

-(void)dealloc
{
    [bar release]; bar = nil;
    [super dealloc]
}



回答4:


Now that I can respond to my question 8 hours later, I'm doing it for anyone who made the same mistake as me during some test or something. However, the answers of sergio and Tommy are very informative.

After reading answers, I saw that I made a silly mistake. During a test of coding of my class, I removed the underscore before my instance variables declaration. So my actual code was truely looking like this:

@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

So the Analyse warnings were correct. Sorry for the false alarm! But thanks for very fast answers.




回答5:


use this ->

@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


来源:https://stackoverflow.com/questions/6124109/instance-variables-with-underscore-in-objective-c-2-0-and-renaming-with-synthet

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!