25

I am using the following code ...

-(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;
}

which generated the following two warnings ...

  • Local declaration of 'variableName' hides instance variable
  • Local declaration of 'comparisonValue' hides instance variable

Is there a common or accepted convention for dealing with these warnings?

I understand that it is simply to inform the user that they should specify an instance when referring to the class member, but its annoying.

Nippysaurus
  • 20,110
  • 21
  • 77
  • 129
  • it's just a warning. you can just ignore it – newacct Mar 29 '10 at 23:32
  • It's not even an issue in this example, since you're accessing all of your instance variables through dot syntax. Even if you used conventional struct dereference syntax (`self->variableName`) there wouldn't be an issue. This warning is only telling you that you can't use `variableName` by itself to refer to the instance variable. – codewarrior Mar 29 '10 at 23:52
  • 4
    Isn't there a pragma to disable this warning? I hate ugly code. – mxcl Nov 26 '10 at 18:13

9 Answers9

33

I see this is a fairly old question with a accepted answer but I have a better solution and its code convention.

The convention states that you prefix private variables with a underscore (_varName) and public (like properties) with just the name.

With this you just can call the same variable name in your functions.

Example:

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
Justin
  • 2,960
  • 2
  • 34
  • 48
  • 1
    Now i know why in that directx book i have read all instance variables have prefix m. Like mVB, mNumRows etc... – Martin Berger Oct 02 '12 at 11:10
  • 1
    This is popular convention in other languages. Also I would like to mention that **Apple Coding Guidelines** allow using an underscore character as a prefix for an instance variable (see typographic conventions [here](http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CodingGuidelines/Articles/NamingBasics.html)) – Vlad May 20 '13 at 15:23
28

Unfortunately, no there's no "good" way to prevent this error. The common pattern is to use a slightly stupid parameter name like

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

    return self;
}
Barry Wark
  • 107,306
  • 24
  • 181
  • 206
4

If your method truly is an initialiser, don't forget to do your self = [super init];.

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

    // do stuff

    return self;
}

I have never personally encountered a situation where self has changed to nil or another value, but it's the Objective-C Initialiser Idiom™.

dreamlax
  • 93,976
  • 29
  • 161
  • 209
  • I knew there was something like that to do ... but this was real quick "filler" code which hasn't really been fleshed out yet :) Thanks for the heads up though :) – Nippysaurus Mar 29 '10 at 23:06
  • 1
    It is better to check on (self) and progress code within that block than use 2 return statements. If [super init] is giving a nil, self will be nil and is returned anyway at the bottom of the method. – Justin Sep 23 '11 at 07:04
3

Either give the local a more descriptive name (e.g. initialVariableName) or give instance variables a different notation (e.g. myClass_variableName). I prefer the latter in most cases because it calls attention to when I'm using class internals rather than the proper interface.

Chuck
  • 234,037
  • 30
  • 302
  • 389
2

Though it's old question but still I've a good solution to suppress warning in code

-(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;
}

You can learn about GCC pragma here and to get the warning code of a warning go to the Log Navigator (Command+7), select the topmost build, expand the log (the '=' button on the right), and scroll to the bottom and there your warning code is within square brackets like this [-Wshadow-ivar]


Edit

For clang you can use

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wshadow-ivar"
// your code
#pragma clang diagnostic pop
Inder Kumar Rathore
  • 39,458
  • 17
  • 135
  • 184
2
_varName = varName;

You can use just this but without the @synthesize - whenever you want to use that variable you just write _*variable name* and it eliminates the error

Albert Xing
  • 5,620
  • 3
  • 21
  • 40
C.Farrugia
  • 4,116
  • 3
  • 14
  • 12
2

This is not a problem at all in the modern Objective-C. In the modern Objective-C, properties are automatically synthesized and their corresponding instance variables get a _ prefix.

So, with auto-synthesis your properties would create instance variables _variableName and _comparisonValue. No shadowing occurs in this case.

More info in this blog post


If you absolutely need to manually synthesize your properties, rename the sinthesized ivar like this

@synthesize variableName = _variableName;

In general case, rename your method arguments.

Alexei Sholik
  • 7,287
  • 2
  • 31
  • 41
1

You should generally prefix instance variables with something like an underscore (e.g. _variableName) to avoid compiler warnings like this.

Otherwise just slightly change the names in your method signature, there is no hard defined naming convention.

indragie
  • 18,002
  • 16
  • 95
  • 164
  • 1
    Apple discourages using underscores for this, because they use this notation for their private instance variables. – Chuck Mar 29 '10 at 22:56
  • Good point, maybe a little more unique prefix would be nicer. – indragie Mar 29 '10 at 23:17
  • @Chuck - Apple discourages using ivars with the initial underscore (or statically scoped variables), but automatic variables like this should be fine. Since you don't compile in the private headers, you won't get the warning, and since you're not (or should not be) accessing those ivars anyway, the automatic scope masking the ivar is not an issue. – Jason Coco Mar 30 '10 at 03:55
  • @Jason Coco: I don't know what you mean "automatic variables like this". The answer suggests prefixing *instance variables*, so I was just pointing out that an underscore might not be the best choice of prefix. – Chuck Mar 30 '10 at 07:16
  • @Chuck: You're absolutely right, I misread the answer. I thought he was prefixing the parameter names for some reason. – Jason Coco Mar 30 '10 at 14:44
0

If you are using local instance variable name same as global instance variable name then this warning occur.

First Methode: For ignoring this warning use have to change local instance variable name or else change the global instance variable name.

Second Methode: if you want to use global variable then call as 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;
}
Nikhlesh Bagdiya
  • 4,316
  • 1
  • 19
  • 29