Objective-C约定防止“本地声明隐藏实例变量”警告

时间:2010-03-29 22:38:01

标签: objective-c

我正在使用以下代码......

-(id) initWithVariableName:(NSString*)variableName withComparisonValue:(NSString*)comparisonValue {

    // super init
    self = [super init];
    if (!self) return nil;

    // set instance variables
    self.mustExist = NO;
    self.reverseCondition = NO;
    self.regularExpression = NO;
    self.variableName = variableName; // generates warning
    self.comparisonValue = comparisonValue; // generates warning

    return self;
}

产生以下两个警告......

  • 'variableName'的本地声明隐藏了实例变量
  • 'comparisonValue'的本地声明隐藏了实例变量

处理这些警告是否有共同或公认的惯例?

我知道只是告诉用户他们应该在引用类成员时指定一个实例,但它很烦人。

9 个答案:

答案 0 :(得分:32)

我认为这是一个相当古老的问题,并且已经接受了答案,但我有更好的解决方案和代码约定。

约定规定,您只需使用下划线(_varName)和公共(如属性)为私有变量添加名称。

这样你就可以在函数中调用相同的变量名。

示例:

ExampleClass.h

@interface ExampleClass : NSObject
{
    NSString *_varName; //this is not required if you create a property
}

@property (nonatomic, retain) NSString *varName;

- (void)someMethodWithVarName:(NSString *)varName;

@end

ExampleClass.m

#import "ExampleClass.h"

@implementation ExampleClass

@synthesize varName = _varName; //if you don't declare the _varName in the header file, Objective-C does it for you.

- (id)init
{
    self = [super init];
    if (self) {
        // Initialization code here.
    }

    return self;
}

- (void)someMethodWithVarName:(NSString *)varName
{
    _varName = varName; //just for example purpose
}

@end

答案 1 :(得分:28)

不幸的是,没有“好”方法来防止此错误。常见的模式是使用一个稍微愚蠢的参数名称,如

-(id) initWithVariableName:(NSString*)theVariableName 
       withComparisonValue:(NSString*)theComparisonValue {
    self.variableName = theVariableName;
    self.comparisonValue = theComparisonValue;

    return self;
}

答案 2 :(得分:4)

如果您的方法确实是初始化者,请不要忘记执行self = [super init];

- (id) initWith...
{
    self = [super init];
    if (!self) return nil;

    // do stuff

    return self;
}

我从未亲身遇到self已更改为nil或其他值的情况,但它是Objective-C Initialiser Idiom™。

答案 3 :(得分:3)

为本地提供更具描述性的名称(例如initialVariableName)或为实例变量提供不同的表示法 (例如myClass_variableName)。在大多数情况下,我更喜欢后者,因为当我使用类内部而不是正确的接口时,它会引起注意。

答案 4 :(得分:3)

虽然这是一个老问题,但我仍然是一个很好的解决方案来抑制代码中的警告

-(id) initWithVariableName:(NSString*)variableName withComparisonValue:(NSString*)comparisonValue {

    // super init
    self = [super init];
    if (!self) return nil;

    // set instance variables
    self.mustExist = NO;
    self.reverseCondition = NO;
    self.regularExpression = NO;


    #pragma GCC diagnostic push
    #pragma GCC diagnostic ignored "-Wshadow-ivar"
    self.variableName = variableName; // generates warning
    self.comparisonValue = comparisonValue; // generates warning
    #pragma GCC diagnostic pop



    return self;
}

您可以了解GCC pragma here并获取警告的警告代码进入Log Navigator(Command + 7),选择最顶层的构建,展开日志(右侧的'='按钮) ,并滚动到底部,警告代码在方括号内,如[-Wshadow-ivar]


修改

对于clang,您可以使用

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wshadow-ivar"
// your code
#pragma clang diagnostic pop

答案 5 :(得分:2)

_varName = varName;

您可以使用此但不使用@synthesize - 只要您想使用该变量,只需编写_*variable name*即可消除错误

答案 6 :(得分:2)

在现代Objective-C中,这根本不是问题。在现代Objective-C中,属性会自动合成,其对应的实例变量将获得_前缀。

因此,通过自动合成,您的属性将创建实例变量_variableName_comparisonValue。在这种情况下不会出现阴影。

blog post

中的详细信息

如果您绝对需要手动合成属性,请像这样重命名sinthesized ivar

@synthesize variableName = _variableName;

一般情况下,重命名方法参数。

答案 7 :(得分:1)

通常应该使用下划线(例如_variableName)为实例变量添加前缀,以避免像这样的编译器警告。

否则只需稍微更改方法签名中的名称,就没有硬定义的命名约定。

答案 8 :(得分:0)

如果您使用的本地实例变量名称与全局实例变量名称相同,则会出现此警告。

First Methode:要忽略此警告,请使用更改本地实例变量名称,否则更改全局实例变量名称。

第二个Methode:如果您想使用全局变量,请调用self->variableName

-(id) initWithVariableName:(NSString*)variableName withComparisonValue:(NSString*)comparisonValue {

    // super init
    self = [super init];
    if (!self) return nil;

    // set instance variables
    self->variableName = variableName; //point to global variableName
    self->comparisonValue = comparisonValue; //point to global comparisonValue

    return self;
}