instance variable shared by objects? - objective-c

I declared an instance variable (not static), just a regular variable in the #implementation section. When I accessed that variable from several objects it appeared that all the objects were sharing the same variable, as if I had declared it static!
I then changed the instance variable to a (strong) property (defined in the .m file to make it private) and it started working as expected, with each object getting their own separate version of the property.
What was going on with that weird "sharing" behavior?

You didn't declare an instance variable. You defined a global variable. You did this:
#implementation MyObject
int myVariable;
but you should have done this:
#implementation MyObject {
int myVariable;
}

When you define a regular var in the #implementation, you define a global variable. For example, in a.m, you define:
#implementation classA
int tryMe = 99;
Then in b.m, you use also use tryMe:
#implementation classB
-(void) func {
extern int tryMe;
NSLog(#"%i", tryMe); // This will print 99.
}
But if you use "static" in a.m, then you will get build error, you will be told that "tryMe" could not be found. Because "static" make the variable local to the file which defines the var.
While, if you define a var as property, then the var is a member of the class, so each instance of the class has its own copy of the var.

Related

Storage of Objective C property variables and non property variables

Can anyone please clarify me that where exactly the variables stored in objective c ?
In .h file
#interface example: NSObject
{
NString *string; // where is this stored
int number; // where is this stored
}
#property (nonatomic,strong) NSURL* mURL; // where is this stored
#end
similarly,
In .m file
# import "xyz.h"
NSString *constant = #"hello"; // where is this stored
#interface example()
{
NString *textg; // where is this stored
int numb; // where is this stored
}
#property (nonatomic,strong) NSURL* sURL; // where is this stored
#end
"string", "textg", "number" and "numb" are instance variables to the class. The difference is that "string" and "number" are eligible to be publicly accessible (via ref->number), and "textg" and "numb" are private (since other classes conventionally do not #import .m files).
"mURL" and "sURL" properties are stored as instance variables "_mURL" and "_sURL". Again, "_mURL" is eligible to be publicly accessible (via ref->_mURL), and "_sURL" is not for the same reason.
And, "constant" is an ordinary global variable stored on the heap.
You ask:
where exactly the variables stored
To answer just this: all the variables other than constant, and the variables used by the properties, are stored as part of the memory allocation for each instance of your class example that you create. Every instance has its own copy of each variable. E.g. when you do:
example *anExample = [example new];
You are requesting that an instance of example is created and a reference to it is stored in anExample. That instance contains the all the instance variables and properties you have declared (and it also contains any instance variables and properties for its superclasses, in this just just NSObject).
Your other variable, constant, is declared at the file level. Such variables are stored along with the compiled code in your file as part of your application. Regardless of how many instances of your class are created there is only ever one constant variable. Methods running on behalf of any instance all see the same constant variable.
HTH

Can the ivar variable created automatically by properties accessible by the child class? [duplicate]

Since recent runtimes in iOS, we are able to define properties that will generate accessors for instance variables. From what I understand, it is not mandatory to declare the instance variable used since it will be automatically done for us.
For example, if I write:
#interface MyFirstClass
#property (readonly, nonatomic) int size;
#end
and in the .m
#implementation MyFirstClass
#synthesize size;
#end
Then an instance variable named "size" will be added for me and a method called "-(int)size" will be implemented.
The problem is that when I create a second class MySecondClass which is a subclass of MyFirstClass, it seems that I can't access the instance variable size within this subclass:
#interface MySecondClass : MyFirstClass
#end
#implementation MySecondClass
- (id)init {
if (self = [super init]) {
size = 10; // this yields and error
}
return self;
}
#end
Are the automatically created instance variables private? Is there a possibility to set them as protected so I can access them in subclasses?
I know there is the possibility to declare the instance variable myself, but I'm just wondering...
With a superclass like this it works: (Is it because it's expressly declared as protected?)
#interface MyFirstClass {
int size; // defined expressly and used as #protected
}
#property (readonly, nonatomic) int size;
#end
Thank you for your help!!
Nicolas.
Any instance variable not declared in the main interface is automatically private, and this cannot be overridden. If you try to use a scope modifier when defining instance variables in the implementation, you will get an error that the specification is inconsistent.
The reason for this is that there is usually only one class per implementation file, which means the compiler doesn't know about the instance variable when compiling other classes. If you have multiple classes in the same file, the compiler could know about it, but you still aren't allowed to override the scope. Possible reasons in this case could be for consistency, or just so the compiler doesn't have to look in so many places for instance variables.
Use:
self.size = 10;
That will map to setSize method.

getter and setter method in objective c?

New to Objective-C, and i am basically from c++ background. I am learning now objective-c and would like to get confirmation of what i understood is write or wrong?. Kindly advise.
I have the following class:
#interface Test: NSObject
{
int instance1;
}
#property int instance1;
- (void) sayHello;
#end
Class 'Test' has a instance variable instance1. If the member function ie: sayHello wants to access the variable, it has to happen through getter/setter functions. So, There are two ways to get it :
User can define.
We can get the help from the compiler?. How?.
declare the same variable as a property, and synthesize it, the the compiler
gets the code of getter/setter for us for that particular variable.
So, Untimately, getter/setter is the only way to access the variable in the method implementation, ie. both self.instance1 = 100; and instance1 = 100 need getter/setter.
Having missed both 1. and 2., there is no way to access the instance1 variable.
Also, instance1 is a pubic variable can can be accessed outside of the class with object instance.
Test *t = [[ Test alloc] init];
t.instance1 = 200;
Questions:
Is there any way to make instance1 is "private", so that I can not access the instance
variable outside the class?
Is there anything wrong in my understanding?
If the member function ie: sayHello wants to access the variable, it has to happen through getter/setter functions.
It doesn't have to. You can access ivars directly, without using accessor methods:
- (void)sayHello {
instance1 = 123;
}
You can define private ivars by declaring them in the implementation file, not the header:
#implementation Test {
int privateVar;
}
// ... additional implementation, methods etc.
#end
Note, that since Xcode 4.4 you don't have to declare your ivars anymore. You simply declare a property. The ivar and the accessor methods will be synthessized automatically.
For more details, I recommend reading my answer to this question: Declaration of variables
ion SomeDelegate.h
#interface SomeDelegate : NSWindowController {
#private
int fLanguage;
int fDBID;
bool fEndEditingIsReturn;
#public
int fIsMyLastMSG;
}
#property int language;
In SomeDelegate.mm
#implementation SomeDelegate
#synthesize language=fLanguage;
In my example you get private and public variables, private variable fLanguage has a property for synthesize accessor methods.

Static variable cannot be accessed from another class

I have a static variable that i want to access from another class in the same project in X-Code. I have declared it in the .h file AND the .m file, gave it a value, and then when i accessed the other class, i got an error message saying that:
"Property 'xx' is not found on object of type 'yy'"
i declared the variable as extern in the .h, and redeclared it as the variable type in the .m. I have tried to change it to static in the .h, but it still doesn't work. And yes, i have imported the file containing the variable, in case that is the problem.
Can anyone help me?
EDIT:
this is the code that i'm currently using:
source.h
static int anObject;
#interface source : NSObject
source.m
static int a = 2
#implementation source
destination.m
# include "source.h"
#implementation destination
- (void) anObjectTestFunction
{
printf("%d", source.anObject); //the first version
printf("%d", anObject); //second version
}
now after i went to the second version, the variable anObject in destination.h can be accessed, but its value is not 2, it's 0. I want it to follow the one i declared in source.h.
I am assuming the static variable declared in the .h file is outside the #interface. So something like:
static NSString *myObjectTest = #"Test";
#interface MyObject : NSObject
#end
If that is the case then you will not be able to access it using something like:
MyObject *obj = [[MyObject alloc] init];
[obj myObject]
or
obj.myObject
That is what is giving you the "Property 'xx' is not found on object of type 'yy'". That static variable is not a property on the object of MyObject.
That static variable is accessible like so myObjectTest as long as you import the .h file
Update
See Chuck's comment below why this is a bad idea to do this way.
You seem confused about what a static variable is. In other languages like Java or C++, "static" can mean one of two things. In a file or function scope, it means a variable scoped to either that file or function that exists for your program's entire lifetime. In a class scope, it means just a class variable.
C++ has both definitions, Java only has the second definition, but Objective-C only has the first definition: A static variable can only be used in the place where it's declared. There is no such thing as an "extern static" variable because the two are contradictory. You probably want either a global variable or a static variable with a class method to access it.
Could this be a namespace issue? Try fully qualifying your access. Posting an extract of your code would really be helpful though, I'm no good at clairvoyance :-)

Undeclared ivars?

I've come across Objective-C code that declares a variable right below the #implementation line in a .m file and not in the #interface block of the .h file. It then proceeds to use it like a private ivar. I haven't been able to find documentation about declaring variables this way and would like to know the impact.
Example:
.h
#interface MyClass {
#private
int _myPrivInt1;
}
#end
.m
#implementation
int _myPrivInt2;
#end
Questions:
What is the technical difference between these two variables?
Is it the same as declaring an ivar in the .h #interface block using the #private modifier or is it more like a C global variable?
Are there any implications when declaring a variable this way?
Should it be avoided?
Is there a term for declaring variables like _myPrivInt2 that would have made my googling a bit more successful?
You must declare instance variables in interface block.
#implementation
int _myPrivInt2;
#end
Declaring variable this way you do not actually declare iVar for your class. _myPrivInt2 will be a global variable and can be accessed from any part of your code using extern declaration:
// SomeOtherFile.m
extern int _myPrivInt2;
...
_myPrivInt2 = 1000;
You can check - your _myPrivInt2 variable will be equal 1000 after code in SomeOtherFile.m executes.
You can also specify static linkage specifier to your _myPrivInt2 so it will be accessible inside current translation unit only
#implementation
static int _myPrivInt2; // It cannot be accessed in other files now
#end