questions about objective-c class methods - objective-c

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

Related

Static variables and memory consumption

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.

Objective-C Property Getter/Setter crash EXC_BAD_ACCESS

I was wondering why assigning values to properties in another class causes EXC_BAD_ACCESS. I can't seem to figure out why.
1.) The value being sent into the setter is non-nil;
2.) When trying to assign the value, EXC_BAD_ACCESS happens, the variable is nil;
Using this pattern in both Cocoa and Cocoa Touch applications both causes EXC_BAD_ACCESS, so I don't think it's the platform, but I believe it's the pattern I'm using.
My questions are, is it when the variables are assigned, or is it the way I'm creating the properties?
I have created a dummy project which is seen in the pictures below.
Any help is appreciated.
EDIT: Doing some digging, I changed the name of the setter's variable (not the property name) to firstName__. Basically, the code in the setter for setFirstName:
- (void)setFirstName:(NSString *)firstName__
{
self.firstName = firstName__;
}
Doing this cleared up a little confusion by saying firstName__ (and not self.firstName) is equal to nil, even though in the AppDelegate, the value is non-nil.
Your problem is recursion. In the setter, you are calling the setter method again, and again and again.
When you declare
self.firstName = first name__;
is basically the equivalent of
[self setFirstName:first name__];
So the method is calling itself which doesn't make much sense to do.
You first need to wrap your head around properties and instance variables.
Objective C class instances often contain instance variables that hold values.
Even though it is possible to expose these variables to outside world via #public qualifier, this is not the established convention.
The convention is to have properties, which behind the scenes are a "wrapper" around private instance variable.
Since in Objective C you can only communicate with other objects via messages, to be able to access the values of instance variable you have setter and getter methods that are invoked when you send an appropriate message to the object.
Modern objective C creates instance variable for you implicitly when you declare properties. It is often said that those properties are backed by instance variables.
Normally there is no reason to explicitly implement setters and getters, as the compiler does this for you behind the scenes. (in a same manner, it also creates those instance variables for you)
But if you want to implement setters explicitly, you need to set the instance variable in the setter, not call the setter itself again (via dot notation convention) as I explained above.
Implicitly created instance variables have a naming convention with underscore as prefix. In your case it is
_firstName
When you declare a property called firstName, you also get an instance variable
_firstName
You setter should look like this
-(void)setFirstName:(NSString *)firstName
{
_firstName = firstName;
}
And getter
-(NSstring *)getFirstName
{
return _firstName;
}

When do we create memory for ivars in Singleton example by Apple?

I have seen the Apple's example of Singleton and couple of other examples.
People say that it is too strict!
But the point is ..even if it is too strict, I want to understand it.
I dont understand that when we call allocWithZone on super, What happens ?
Memory will be created according to super's instance size.
What if our Singleton has ivars ?
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaObjects/CocoaObjects.html#//apple_ref/doc/uid/TP40002974-CH4-SW32
I also dont understand that, Why does allocWithZone return the object with a retain call when retain itself is returning the object as it is.
Whenever a method is called in Obj-C it is passed an object reference via the hidden parameter self. For an instance method self refers to the object the method was invoked on, for a class method self refers to the the class object (of type Class) the method was invoked on. Calls to super implicitly pass on self.
Therefore in Apple's example code the call [super allocWithZone:NULL] calls the super implementation of allocWithZone passing the current value of self, which is MyGizmoClass's class object as it is a static method. The implementation of allocWithZone can determine the required memory size from the passed Class object – the details of how are private.
As you've correctly spotted, the call to retain in allocWithZone is pointless but harmless.

Class methods and instance methods - when/when not to use them?

I was wondering when and when not to use class methods and instance methods. I need some practical examples. I am really confused. Another question: can't we do exactly the same things with instance methods that we can with class methods?
Class methods: The method isn't tied to any specific object. In a way it acts like a free function in the class's namespace. No 'self' pointer. For instance [UIScreen mainScreen] is a class method because there's only one screen and there's no need to care about multiple 'screen instances'.
Instance method: Tied to a specific object.
This applies to most OO languages, not just obj-C.
At the implementation level, an instance method call contains a hidden pointer to a data structure (the object), a class method does not.
The practical question to ask is whether your call requires sending the call some specific data which is or could best be encapsulated as instance data inside an object, or not.
You (usually) can do the same thing with class methods as instance methods, but then you have to explicitly pass the object as a visible parameter in the call, which is uglier looking and also potentially disables some method override features of the Objective C language.
Use class methods for utility functions and Instance methods for object oriented stuff.
Eg. For Mathematical calculation (eg sin x ) use class method. But for invoking a behavior specific to an object.. use instance method ..
A class method as the name implies is bounded to the class. You can invoke them just with the name of the particular class. These can be normally exposed methods of a class.
For example
NSArray
+ (id)arrayWithArray:(NSArray *)array;.
You call it with the class name NSArray. What you expect is just a creation of a object of the type of that particular class. This doesn't need an object to invoke. Also these are very basic method required so its better to make it as a class method.
On the other hand instance method as the name implies is very much bound to the instance. Object is an entity that encapsulates state (ivars) and behaviors (methods) of a class. This can be very specific to the object.
For example
- (NSUInteger)count;
Lets take NSArray *a and NSArray *b. If a contains 5 items whereas b contains 4, instance methods called upon these instances will produce different results. And thats why we need instances to be initialized while invoking instance method. They work on the context(or state) of the object they are been called upon. Also they are not exposed as the class methods are.
Hope this helps.
If you want to use instance objet or instance variable you have to go with instance Methods.
Bcz Inside the class you cant access the Instance instance objet or instance variable.
Class methods are static methods.

share a property among different instance of the same class

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.