Is it possible to share one parameter of a class among all the instances of this class, in objective-c?:
#interface Class1 : NSObject {
NSString* shared; /** shared among instance (this is not, but defined somehow) **/
NSString* non_shared; /** other parameters non shared **/
}
In the program then, each instance of Class1 has its own non_shared variables (as usual), but all access the same shared one (when one instance changes it all can see it).
One possibility is to hide the variable as a property and use a singleton in the setter/getter functions, but I don't know if there is a simple way.
Thanks,
Edu
Class variables (called static in many other OOP languages) are actually a bit of a pain in Objective-C. You have to declare a static global variable in the class' module (.m) file and reference that variable. You should add class-level getter/setters to encapsulate access to the static global variable. Your getter can alloc/init an object and put it in the variable if it is uninitialized before returning it.
If the static variable holds an instance (e.g. an NSString instance in your example), you need to make sure it doesn't get alloc/initialized more than once. Take a look at dispatch_once if you're on OS X 10.6 or greater to guarantee single initialization.
Related
With iOS, we always have to be concerned about memory consumption.
I have a class that may have hundreds of instances, and I haven't been able to locate a discussion that indicates whether declaring a static dictionary inside an instance method means that all instances of that class will share the same copy of that dictionary, or each instance will have its own copy, which of course would demolish memory.
BTW, would the answer be any different if this were a class method instead of an instance method?
-(BOOL)doohickeyThing
{
static NSDictionary *someDictionary = [NSDictionary dictionaryWithObjectsAndKeys...
// more code here
}
Thanks.
By definition, there is only one copy of a static variable. No matter how many instances of your class you have, there will only be one copy of the someDictionary. It will get initialized once and every time the method is used, regardless of class instance, the same exact dictionary instance will be used. In other words, it is shared.
This is true whether it is an instance method or a class method.
I already understand that static in objective-c is different from static in say Java. My question is for Objective-c static variables. I have a static variable in Objective-C. If it is set in one instance of a class. Will the value be visible if I were to create a new instance of the class after the variable was previously set?
Yes, that's the point of static variables. They are not instance variables. A static variable exists just once in its scope. It is initialized once as well.
This is true for static variables declared outside of any method as well as static variables declared within a method.
The static keyword is merely used to limit the scope of a variable so that it can only be referenced directly within its implementation file.
The static keyword is commonly used with global variables to implement Objective-C's half-baked class variables, so yes, you are correct, that a single instance of the variable will exist regardless of the number of instances of the class (including zero), and that's basically because it's completely unrelated to the class.
Since Objective-C doesn't support const instance variables in classes what are some alternatives to ensure the value of the variable doesn't get changed? I do not want to resort to preprocessor #defines because I would prefer class variables. Also, is there a reason const instance variables aren't supported?
Objects in Objective-C are constructed differently than those in C++ or Java. All instance variables are initialized to zero by the alloc method, before the init method is called, so it would be too late by the time init is called to change a const instance variable. Obviously the compiler writers could modify the compiler to support changing a const instance variable in an init method, but they haven't done so.
Typically you just make your instance variables #private and expose them using accessor methods. If you don't want an instance variable's value to change, don't expose a setter method and don't modify the variable in your class implementation.
If you drop support for 32-bit Mac OS X, you can put your instance variables in your #implementation instead of your #interface, which completely protects them from meddling by other classes.
What is the difference between declaring variables in the interface section vs. in the implementation section outside of a method.
Do you mean in the ivar block in the implementation, as in
#implementation MyClass {
id someIvar;
}
// methods go here
#end
If so, then the only difference is visibility to other code. At runtime, the ivar will be indistinguishable from one declared in the #interface section. However, code outside the class can see ivars declared in #interfaces, and unless those ivars are marked with #protected or #private, then the other classes can reach in and twiddle the ivars. But ivars declared in the #implementation are not even visible to code outside, so they cannot touch the ivars.
For the most part, this is just a code cleanliness issue. Nothing should go in the header file unless it's meant to be public. So why put ivars there?
As Josh Caswell noted, ivars declared in this fashion require a recent version of Clang.
The alternative interpretation of your question is you have code like
#implementation MyClass
- (void)someMethod { /* ... */ }
NSString *var;
- (void)otherMethod { /* ... */ }
#end
If this is what you meant, then the answer is, don't do that. In this code snippet we've declared a global variable named var rather than an instance variable. The location of the variable inside the #implementation block is irrelevant, it's exactly identical to a global variable in C (because that's what it is).
A variable declared in the #interface is an instance variable. In more recent compilers instance variables can also be declared in a block in the #implementation in a similar way to doing so in the #interface - this effects their visibility but not their lifetime.
A variable declared "outside of a method" in the implementation, as in:
#implementation
static int CallCount = 0;
is the closest thing Objective-C has to a class variable - a variable which all instances of a class share, as opposed to instance variables where each object instance has its own variable.
Such a variable has execution lifetime - it exists throughout a single execution of the whole application - just as typical class variables do in other languages. (The lifetime of instance variables is that of the object instance they belong to.)
The use of static further limits the visibility (not its lifetime) of the variable name to just the file containing the declaration - like a private class variable in other languages. Note that, unlike most languages class variables, variables declared in an #implementation without a static qualifier are added to the global namespace and thus increase the opportunities for name collisions - this is why they are not real class variables.
Such class variables are often initialized using the class method + initialize, just as instance variables are initialized using the instance method - init.
Declaring them in a class extension is often used in attempt to hide the instance variables and associated accessors from the client. Neither approach truly hides them, but hiding them is usually an improvement, and is available only if all compilers you need support it.
I know that class variables are declared in memory (as opposed to on the stack) when the class is initialized, and I know how class methods are basically used. But I have some questions about class methods that aren't answered in the basic documentation.
Are class method also declared in memory? What about any object declared within these class methods? Are they 'static' in scope? What about any objects that are passed into a class method as parameter? Are those also 'static'?
Does repeatedly calling a class method mean all the objects declared within it are allocated again and again (one per method call), or are they living in one location in memory? Do they get cleared at every run?
For example, what happens to the do_something method here:
+ (void) main
{
while (i < MAX)
{
[MyClass do_something];
}
}
+ (void) do_something
{
NSMutableArray *array = [[NSMutableArray alloc] init];
...
[array release];
}
Class methods follow the same rules as object (instance) methods except you cannot access instance variables from class methods, obviously because ivars get allocated per object instance.
In your example "array" is allocated on heap with each call, as usual.
All variables are stored "in memory", no matter their storage type (static, automatic, free store), location (stack or heap), linkage or scope. A variable is static only if it's declared static. Otherwise, variables in class methods, whether parameters or local variables, have function or local scope, automatic storage, no linkage and are stored on the stack.
Class methods have global scope and external linkage, though you can send a message to an object (including classes) even if there isn't a handler in scope. Internal linkage should be possible, but I don't think the language supports declaring methods with internal linkage. Storage type and location doesn't really apply to methods, but you could say methods have static storage.
When calling the +(void) do_something method the array object will be initialised, as your code specifies, every time. It is only declared the scope of that method.
You can declare static variables in the class scope. These, as you'd expect, are accessible to all instances and class (aka static) methods.
See: http://www.otierney.net/objective-c.html#class