关于iphone:在Objective-C 2.0中使用下划线并使用@synthetize重命名的实例变量通过Xcode 4的“Analyze”工具导致优化警告

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

本问题已经有最佳答案,请猛点这里访问。

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

我正在使用相同的约定,例如变量和属性命名,如sebnow在下面的答案中所示:

目标C中的实例变量/方法参数命名

我把他的示例代码粘贴在这里:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@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

在实现foo类的某些方法时,我使用了以下示例:

1
_bar = aBar

而不是使用:

1
bar = aBar

xcode 4引入的'analyse'工具给出了这个警告(我使用的是4.0.2版):

类"foo"中的实例变量"bar"在其@implementation中从未被方法使用(尽管它可能被category方法使用)

也许我应该使用:

1
self.bar = aBar

但是对于只读属性,这是不可行的,除此之外,我不确定在类本身中使用setter是否是一种好的实践。

我对目标C不熟悉,但我仍在学习的初期。也许我做错了什么,在某个地方有一个糟糕的编码实践。

如果您能帮助我,请提前感谢您;)


@synthesize行影响属性"bar"的setter和getter的操作方式。线:

1
@synthesize bar = _bar;

有效地说,"按照我声明为@property的方式,放入标准的bar getter(和setter,如果相关的话),但使用实例变量"bar作为存储。

当您使用self.bar作为左值时,实际上是对[self setBar:]进行方法调用,而当您将其用作右值时,实际上是对[self bar]进行调用。它看起来像一个普通的C样式结构成员访问,但在内部它是一个方法调用。

因此,@synthesize创建了一个适合self.bar使用的getter和setter,但不会更改实例变量的名称。因此,当您直接从类内访问对象时(尽管现在有些人从风格的角度对此表示不满),您应该有权使用_barself.bar,否则,不会收到任何分析器警告。

如果您最终得到一个名为bar的实例变量,假设您没有在接口中声明它,那么最可能的错误是在执行@synthesize的方式中出现了错误。在现代运行时,您可以为接口中没有实际声明的变量提供一个@property/@synthesize对,该变量将神奇地添加到接口中。所以如果你犯了一个不幸的错误,你可以不小心做到。

如果可能的话,你能公布你的实际代码吗?


"从不使用"应该从字面上理解:你只在作业中定义它的价值,不要使用它。

对于局部变量,这是同样的警告:如果只定义它们的值而从不使用它,那么它们的作用是什么?

因此,静态分析器会警告您,因为通常从未访问过的变量只是已更改的旧代码的剩余部分,您可以删除它们。但在你的情况下,可能会非常好。


现在我可以在8小时后回答我的问题了,我是为那些在某些测试中犯了和我同样错误的人做的。然而,塞吉奥和汤米的回答是非常有信息性的。

看完答案后,我发现我犯了一个愚蠢的错误。在对类进行编码测试期间,我在实例变量声明之前删除了下划线。所以我的实际代码是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@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

所以分析警告是正确的。对不起,虚惊一场!但谢谢你的快速回答。


请看我的评论。

尝试添加一个-dealloc方法来释放对象。这将"访问"IVAR,并应使静态分析仪满意。

1
2
3
4
5
-(void)dealloc
{
    [bar release]; bar = nil;
    [super dealloc]
}

使用这个->

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@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