Are "local object variables" the variables that are used or initialized in a method, or are they the arguments taken in? I can't find this term in Xcode's documentation or Google.
I found this in the Objective-C book that I'm using. The full quote is
Local variables that are basic C data types have no default initial value, so you must set them to some value before using them. The three local variables in the reduce method are set to values before they are used, so that's not a problem here. Local object variables are initialized to nil by default. Unlike your instance variables (which retain their values through method calls), these local variables have no memory. Therefore, after the method returns, the values of these variables disappear. Every time a method is called, each local variable defined in that method is reinitialized to the value specified (if any) with the variable's declaration."
Based on your comment, I understand what the book means. Local variables are variables local to a particular scope (denoted by braces '{}' in C and Objective-C). Local variables are declared in the scope where they're used, as opposed to global variables which can be seen and used globally (to a file, multiple files or the whole program depending on declaration visibility). Instance variables are part of a class instance and can be used by any of its methods (and other classes too if declared using #public, though that's generally not good practice).
Primitive local variables are local variables whose type is a C primitive like int, float, char, etc. What the book is calling "local object variables" are simply local variables whose type is (a pointer to) an Objective-C object. Examples are NSString *, NSDictionary * and id.
Local variables are stored on the stack, as opposed to the heap. Variables on the stack go away at the end of the method or function call where they were declared. This Stack Overflow question has some good answers explaining the difference between the stack and the heap: What and where are the stack and heap?
The first result of a Google search for "local variables objective-c": http://blog.ablepear.com/2010/04/objective-c-tuesdays-local-variables.html .
Local variables are defined in the method and scope of the variables that have existed inside the method itself.
Related
int anInteger = 42;
void (^testBlock)(void) = ^{
NSLog(#"Integer is: %i", anInteger);
};
anInteger = 84;
testBlock();
Integer is: 42
This is an example from Apple official guide.
Now, for object value, it is easy to understand, it keeps a reference to it. So later on, when it's original reference changes to point to something else, or simply gets destroyed. This reference is still there, so reference count won't be zero, and the original value is kept.
But, for the example code above, it is not an object. The block keeps a reference to it, and then the value changes to 84. I suppose that is a change to itself instead of its copy, that means the value the pointer pointing to has changed. How can it still be 42?
From the Blocks and Variables section of the documentation:
The following rules apply to variables used within a block:
Global variables are accessible, including static variables that exist within the enclosing lexical scope.
Parameters passed to the block are accessible (just like parameters to a function).
Stack (non-static) variables local to the enclosing lexical scope are captured as const variables.
Their values are taken at the point of the block expression within the program. In nested blocks, the value is captured from the nearest enclosing scope.
Variables local to the enclosing lexical scope declared with the __block storage modifier are provided by reference and so are mutable.
Any changes are reflected in the enclosing lexical scope, including any other blocks defined within the same enclosing lexical scope. These are discussed in more detail in The __block Storage Type.
Local variables declared within the lexical scope of the block, which behave exactly like local variables in a function.
Each invocation of the block provides a new copy of that variable. These variables can in turn be used as const or by-reference variables in blocks enclosed within the block.
Rule 3 applies to the code in your question.
Blocks introduce the necessary indirection to make sure this happens. Variables that appear to be local but which are captured by blocks are actually allocated on the heap by the compiler. Among other things, this is necessary for that variable to be able to outlive the lifetime of the function it was declared in.
To make a long story short: Integral values are copied. (To be more precise: structs and object references are copied, too. But in the case of object references, it is a reference.)
BTW: This is the meaning of a closure. This is what closure are made for. The reason for their existence. You want exactly this behavior. Otherwise you would have to ensure, that a value is not changed while a block is running – maybe seconds or minutes later.
I would like to ask a question, about an 'Object' and 'variable' in Objective-C. As we know, we can take many variables to store data of an object, but first we have to create an object with allocation. We have to give a memory location for our object in RAM using 'alloc' keyword. I think object can't store data because, an object is a noun, like a person. So, to store a data we need to use a variable. In C or C++ we use a variable of any primitive data type for data storage purpose. In Objective-C we use predefined classes like NSString.
So, can I use a variable with my NSString class type or I will use only an object with class type object.
There are two problems for me.
NSString *xyz = [[NSString alloc] init]; // can anyone tell me what should be 'xyz' in here a 'variable' or an 'object'?
if 'xyz' is an object in here. So, firstly I have to create it. But somewhere I have seen like....
NSString *xyz = #"welcome"; // according to me, here we are not allocating memory for 'xyz'. Why?
What is the difference between both statements? Can you please tell me?
Objects are instances of classes. (And that's all there is. Nothing else needs saying).
Variables are global and static variables (having unlimited life times) and automatic variables (variables existing while a function is executing, or while a new scope in a function is entered), and disappearing when the scope ends or the function returns.
In Objective-C, objects can never be variables. Pointers to objects can be variables, but objects can't. Values that are part of an object are often called "instance variables", but that is not the same as a variable.
In other languages, like C++, objects can be variables. The question "what is the difference between objects and variables" doesn't really make sense. It's like asking "what's the difference between alcohol and a cow". They are different categories of things.
#"MyString" is a shortcut; the compiler will create an object for you and give you a pointer to that object.
I have the following code under ARC:
-(void) foo {
__block int spam = 42;
self.myProperty = ^{
spam++;
}
self.myProperty(); // Increment first time
}
-(void) bar {
self.myProperty(); // Increment second time
}
When "Increment first time" is called, ObjC uses pointer to spam (which resides on stack) to increment it, right?
After it, foo stack is thrown out, so pointer is not valid anymore.
What will bar do? What should happen when I call it?
Everything is clear about objects, since they are created on heap and block copying (which takes place in the moment of property assignment) leads to retain call. But what is about auto vars?
I can use debugger to find the answer, but I want to fully understand it: which part of Objc/clang specification covers that?
Update: A used "&" to get address of my variable and found that address get changed in the moment I assign block to my property (actually at the moment when block is copied). I believe that is the moment from my variable was moved from stack to heap.
-(void) foo {
__block int spam = 42;
int* addrOfSpam = &spam;
*addrOfSpam = 43; // OK, spam = 43 now
self.myProperty = ^{ // The moment when spam is moved from stack to heap
spam++;
};
*addrOfSpam = 44; // Fail, spam not changed and 'addrOfSpam' points to nowhere
spam++; // Spam looks like auto/stack var here, BUT IT IS NOT!
// It is on heap now, and "spam" is changed by compiler to:
// *(newAddressOfSpamInHeap_OnlyCompilerKnowsWhere)++;
}
The salient passage in the doc is here. (boldface added by me)
__block variables live in storage that is shared between the lexical scope of the variable and all blocks and block copies declared or
created within the variable’s lexical scope. Thus, the storage will
survive the destruction of the stack frame if any copies of the blocks
declared within the frame survive beyond the end of the frame (for
example, by being enqueued somewhere for later execution). Multiple
blocks in a given lexical scope can simultaneously use a shared
variable.
The block qualifier places the variable in a scope that will persist at least as long as the block that refers to it. So the first and second invocations of the block are identical with respect to the variable. After the second call, spam should equal 44.
First of all, __block is a storage qualifier for variables, and it the same way for all types of variables. Whether it's a variable of primitive type, pointer-to-object type, or whatever (by the way, a variable cannot have "object type"); doesn't matter. Variables of all types normally reside on the stack if they are local variables of a function. Referring to a local variable of pointer-to-object type after its scope has exited equally results in undefined behavior.
About your question, the answer is that __block variables are not only stored on the stack. They can also be stored on the heap. How it works is an implementation detail but it's guaranteed by the specification to be valid to be used in all the blocks that capture it.
If you want to know how it is actually implemented, you can read Clang's Block implementation specification (although I think there are some typos). Essentially, when you have a __block variable, you actually have a data structure, where the variable is a field. And the data structure also has a pointer to keep track of where the current version of itself is. Accesses to the variable are implicitly translated by the compiler to access it through these levels of indirection.
Just like with blocks, this data structure starts out on the stack for optimization, but can be "moved" to the heap (it gets moved the first time any block that captures it gets moved to the heap, because that's when its lifetime might need to exceed the scope it was created in). When it's "moved" to the heap, the pointer that says where it is is updated, so that people will know to use the new copy. This data structure, when in the heap, is memory-managed by a system of reference counting.
Blocks that capture __block variables have a copy of the "current version" pointer, which is updated when the data structure is moved, so they know where to access the variable both before and after the move.
About your tests, you have to be really careful about taking the address of a __block variable, because the location of the variable moves over its lifetime! (something that doesn't usually happen in C).
When you first take the address of spam, it is still on the stack, so you have the address of the stack version of it. spam is captured in a block which is then assigned to the property myProperty whose setter copies the block, moving it to the heap and also moving spam to the heap. addrOfSpam still points to the stack version of the variable which is no longer the version being used; using it to change the integer is changing the wrong version of the variable, because everyone is using the heap copy now.
What is the difference between the code below?
#implementation MyClass
static int myVar =0;
int _myVar =0;
I am getting same values for different objects of MyClass and both are visible to the all methods of MyClass...
Static and global variable differ a lot in their behaviour to life and scope. First, let me distinguish between life and scope. Life of an object determines whether the object is still in the memory (of the process) whereas scope of the object is whether can I know the variable by its name at this position. It is possible that object is live, but not visible (not in scope) but not that object is not alive but in scope (except for dynamically allocated objects where you refer object through pointers).
Static variables are local in scope to their module in which they are defined, but life is throughout the program. Say for a static variable inside a function cannot be called from outside the function (because it's not in scope) but is alive and exists in memory. The next time this function is entered (within the same program) the same chunk of memory would be accessed now retaining the variables old value and no new memory is allocated this time for this variable like other variables in the function (automatic variables). So basically the variable persists throughout the program. Similarly if a static variable is defined in a global space (say at beginning of file) then this variable will be
accessible only in this file (file scope).
On the other hand global variables have to be defined globally, persists (life is) throughout the program, scope is also throughout the program. This means such variables can be accessed from any function, any file of the program.
So if you have a global variable and u r distributing ur files as a library and you want others to not access your global variable, you may make it static by just prefixing keyword static (of course if same variable is not required in other files of yours).
Neither of those variables are related to MyClass and both are global, which is why you are seeing the same value in all instances of MyClass. If you wanted to make _myVar an instance variable then it needs to go between brackets:
#implementation MyClass {
int _myVar;
}
...
#end
The difference between the variables in your code is that the static variable cannot be accessed outside the scope of the implementation file (which I assume is called MyClass.m), while the non-static one can be accessed from anywhere in the application, however you'd need to keep the compiler happy with an extern int _myVar; in any code that wants to access it; this is normally done by putting that extern declaration in a header file.
static limits the scope of your variable. In your case variable will be visible within MyClass file.
However, declaration of variable without static means that variable is automatic by default. It means that your static will live throughout all method calls and automatic will be allocated when you call a method and then at some point deallocated.
This question already has answers here:
Class variable defined at #implementation rather than #interface?
(6 answers)
Closed 7 years ago.
What is the difference between
#implementation aClass {
aType *aVariable
}
- (void)aMethod: {
}
and
#implementation bClass
bType *bVariable
- (void)bMethod: {
}
Is bVariable global?
Is bVariable global?
Yes.
Objective-C is an extension of C and this is a standard C global variable declaration.
You probably should also look up the meanings of static and extern in relation to global variables in C.
HTH
Addendum
So back to the first question, the difference is that I can't define bVariable again in my entire project, while the term aVariable can be reused?
Short answer: No, at least not how you've expressed the question.
Long answer: What you have are two declarations each of which declare a variable and associate a name (or identifier) - aVariable, bVariable - with that variable. As well as a type, which is part of the declaration, a variable has a lifetime - how long the variable exists - and a scope - the part of the program in which the variable is accessible. Scopes can nest, and inner scopes can contain declarations which use the same name's as those in outer scopes, which results in hiding - the variable in the outer scope cannot be directly accessed via its name.
A global variable is one whose lifetime is the whole execution of the program, however the scope in which a global variable is (directly) accessible need not be the whole program (c.f. the static qualifier in (Objective-)C), and different global variables with non-overlapping scopes can have the same name.
An instance variable is one whose lifetime is the same as that of its owning class instance, and whose scope is the members of the class.
There are also local variables, whose lifetime and scope is the containing method, function, block etc. that declare them.
The above is just a quick summary, you should look up the meanings of the all italicised terms.