45

I'm new to Objective-C, but I am curious about something that I haven't really seen addressed anywhere else.

Could anyone tell me what is the difference between a private variable that is declared at the @interface block versus a variable that is declared within the @implementation block outside of the class methods, i.e:

@interface Someclass : NSObject {

 NSString *forExample;

}

@end

vs.

@implementation Someclass

 NSString *anotherExample;

-(void)methodsAndSuch {}

@end

It seems both variables ( forExample, anotherExample ) are equally accessible throughout the class and I can't really find a difference in their behaviour. Is the second form also called an instance variable?

1
  • If you have @implementation Someclass { NSString *anotherExample; } the answer would be completely different Commented Jun 12, 2023 at 5:29

7 Answers 7

35

The latter is not defining an instance variable. Rather, it is defining a global variable in the .m file. Such a variable is not unique to or part of any object instance.

Such globals have their uses (roughly equivalent C++ static members; e.g. storing a singleton instance), but normally you would define them at the top of the file before the @implementation directive.

Sign up to request clarification or add additional context in comments.

4 Comments

This is what I suspected and your answer makes perfect sense, but if I try to access anotherExample in any other class (by properly including Someclass in those classes) the compiler tells me that this variable is undeclared. What gives?
@bitcruncher because anotherExample is only global to the .m file in which it was declared. If you want it available to other files, you'll have to declare extern NSString * anotherExample; in the .h file, then #import the .h file wherever you need the global. This reeks of a code smell, although it does have valid uses cases.
no actual code is smelling :-) this was just an exploratory question.
FWIW, ivars can now be declared in brackets after @implementation SomeClass. I keep forgetting it....
24

They're very different! The one in @implementation is a global variable not unique to each instance. Imagine there were accessors for both variables, written in the obvious way. Then the difference in behavior is shown here:

Someclass* firstObject = [[Someclass alloc] init];
Someclass* secondObject = [[Someclass alloc] init];

//forExample is an instance variable, and is unique to each instance.
[firstObject setForExample:@"One"];
[secondObject setForExample:@"Two"];
NSLog(@"%@",[firstObject forExample]); //Result: "One"
NSLog(@"%@",[secondObject forExample]); //Result: "Two"

//anotherExample is a global variable, and is NOT unique to each instance.
[firstObject setAnotherExample:@"One"];
[secondObject setAnotherExample:@"Two"];
NSLog(@"%@",[firstObject anotherExample]); //Result: "Two" (!)
NSLog(@"%@",[secondObject anotherExample]); //Result: "Two"

//Both instances return "Two" because there is only ONE variable this time.
//When secondObject set it, it replaced the value that firstObject set.

If you are looking for this sort of behavior, you might be better off using a class variable, like this:

static NSString* yetAnotherExample = nil;

Then you can use class methods to interact with the variable, and it's clearly class-specific (as opposed to instance-specific or global).

4 Comments

So would anotherExample be a program-wide global variable or a class global variable? In other words is anotherExample a global variable that exists always or is it a global that exists when Someclass is instantiated?
It exists always. You could declare extern NSString* anotherExample in another .m file and use it again. Please don't. But you could. :P
please don't think i actually code this way. :-) just trying to understand why others were doing this (doom for iphone, for example)
This explains global variable not unique to each instance phrase in a lucid manner. It deserves many upvotes.
5

If you declare a variable inside the @implementation section, you're actually creating a global variable, visible everywhere (in every method in your application).

Member variables can only be declared in the @interface section. They are only accessible in the class itself.

Comments

3

The private block declared inside the @implementation block is kind of dangerous, seems to me, comparing with other OOP concept e.g. Java. Its look like member variable but kinda static.

Novice programmer can easily fooled with it. I write a test program and surprised with the behaviour.

@interface SomeClass : NSObject
{
    NSString *forExample;
}

- (void) set:(NSString *)one another:(NSString *)another;
- (void)print;

@end

Implementation:

#import "SomeClass.h"

@implementation SomeClass

NSString *anotherExample;

- (void) set:(NSString *)one another:(NSString *)another
{
    forExample = one;
    anotherExample = another;
}

- (void)print{
    NSLog(@"One = %@, another = %@", forExample, anotherExample);
}

@end

Test:

- (void)testClass {
    SomeClass * s1 = [SomeClass new];
    [s1 set:@"one one" another:@"one another"];
    SomeClass *s2 = [SomeClass new];
    [s2 set:@"two one" another:@"two another"];
    [s1 print];
    [s2 print];
}

And the output is,

One = one one, another = two another
One = two one, another = two another

Comments

2

Use a code snippet to tell the difference between a member variable and a global variable:

@implementation MyClass {
  // It is an ivar, or called member variable
  // Can NOT be initialized when defined.
  // Can be accessed with `self->_i`
  int _i; 
}

- (instancetype)init {
    if (self = [super init]) {
       _i = 2; // should be initialized before being used.
    }
    return self;
}

int i = 9; // Global variable, and can be initialized when defined.
- (void)myFun {
    NSLog(@"%i, %i", self->_i, i);
}

@end


// Another file

extern int i;
NSLog(@"%i", i);

1 Comment

Update: property is much more recommended by Apple.
0

Just to be clear, never ever ever declare an IBOutlet as a global var (in the implementation) if you are using it for localized nibs/xibs.

I spent a few hours figuring why the outlet is connectable only in one of the localized nibs at any given time.

Thanks for this question and the answers!

Comments

-1

The answers inside this pages are obsolete. Now (2024) you can define instance variable inside implementation section.

"You Can Define Instance Variables without Properties" section inside "Encapsulating Data" page in Programming with Objective-C page. Encapsulating Data

@implementation SomeClass {
    NSString *_anotherCustomInstanceVariable;
}
...
@end

I know it's already outdated, but Google sometimes show this answer at the top, which is misleading now. So I'm adding this answer.

2 Comments

No, the other answers are not obsolete. The other answers actually answer the question that was asked. While your answer is correct, it doesn't address the question that was asked. Also, your answer has been valid for at least 15 years. It's not at all new to 2024.
I see, I'm wrong. I thought the comment for instance varible inside implementation section is valuable for this title, but DawnSong's answer stackoverflow.com/a/50848921/4369828 already mentions it. I thought this feature is added recently (apple doc says historically and my book says it is supported XCode 4.2), but it's more than decade as you said.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.