Objective C object alloc and release - objective-c

I am new to objective C. I want to know why some classes do not need alloc when building an object. For example, the class NSNumber. To build an object:
NSNumber * strangeNum;
strangeNum = [NSNumber numberWithInteger:100];
No alloc and no release are needed.
But if I define a class myself, say myClass and build an object. I need to
myClass * myObj=[[myClass alloc] init];
...
[myObj release] // if without ARC
Can somebody explain this in detail? Thanks a lot.

The release method has been pretty much obsoleted by ARC (automatic reference counting), and you'll rarely, if ever, come across it with newer (the past couple years) code. To understand why you don't call release on an object you get from numberWithInteger:, you need to read the memory management policy for Objective-C, which can currently be found at this link.
The alloc method is a class method, and is the canonical way to allocate memory for any class which descends from NSObject. Classes may have any number of class methods, and a class method can create an object on your behalf. Somewhere in the chain of method calls, alloc will be called, it is just that for Foundation classes, which you don't have the source for, you don't see it.

First case - +[NSNumber numberWithInteger:]. It's a class factory method. From Apple documentation:
Class factory methods should always start with the name of the class
(without the prefix) that they create, with the exception of
subclasses of classes with existing factory methods. In the case of
the NSArray class, for example, the factory methods start with array.
The NSMutableArray class doesn’t define any of its own class-specific
factory methods, so the factory methods for a mutable array still
begin with array.
Class factory method return autoreleased object. Usually it's used as a simple shortcut, that calls corresponding init method:
+ (NSNumber)numberWithInteger:(int)intVal {
return [[[self alloc] initWithInteger:intVal] autorelease];
}
Second case is an explicit creation of NSNumber instance. Because you didn't call autorelease right after instance creation, you should call release after you've finished using object to free allocated memory.
So, object instance in both cases built trough alloc and init calls sequence.

Actually NSNumber does need an alloc, but you are using a static method which does the alloc.
If you were to see the source code for NSNumber, its static method(non instance method) for numberWithInteger would probably be something like this
-(NSNumber)numberWithInteger:(int)intVal {
NSNumber num = [[NSNumber alloc] init];
*Some magic*
}
Basically Apple have just made some it easier for you.

Related

Objective C - How to call class methods without allocating and initializing an object

I'm new to Objective-C and I'm finding the syntax of valid Objective-C code hard to understand. For example, all objects are normally allocated and initialized using the MyClass *myObject = [[MyClass alloc] init]; syntax. However, in the example below, a method is called on the "NSKeyedArchiver" class before creating an initialized object of that class. The same situation happens in the next line of code, where a method is called on "NSUserDefaults" without creating an allocated/initialized object. How is this possible?
NSData *bandObjectData = [NSKeyedArchiver archivedDataWithRootObject:self.bandObject];
[[NSUserDefaults standardUserDefaults] setObject:bandObjectData forKey:bandObjectKey];
Thanks!
These are called class methods and they don't require an instance of a class to be performed because they don't depend on an actual class instance. You can actually create your own by prefacing the method with a + sign (as opposed to a - sign)
We generally use class methods when we don't depend on an instance of a class. So in your examples, the NSKeyedArchiver class doesn't need an instance of itself to be created in order to archive data. Similarly, you can get the standard NSUserDefaults without having a NSUserDefaults object created.
The other types of methods (instance methods) are used when the object itself needs to change its state.

How can I use a constructor class method in a subclass? [duplicate]

Apart from the standard [[MyClass alloc] init] pattern, some objects are built from static methods like MyClass *obj = [MyClass classWithString:#"blabla"]
According to widespread memory management guides (including Apple's), you're only responsible for releasing the objects that you alloc.
Can anyone provide me with a template for such methods? How do you return the allocated object ([self alloc]; return self;, perhaps)? How do you make sure that it will be released?
They are class methods, not static methods1. This specific type, creating autoreleased objects, can be referred to as "factory methods" (formerly also "convenience constructors"), and they are discussed in the Concepts in ObjC Guide. They go something like this:
+ (instancetype)whatsisWithThingummy: (Thingummy *)theThingummy {
return [[self alloc] initWithThingummy:theThingummy];
}
Where Whatsis is your class, and Thingummy is another class which your class uses.
If you're not compiling with ARC, the convention is to autorelease the instance before returning it.
The instancetype keyword was introduced by Clang for these kinds of methods; combined with self (which is the class object itself2 in a class method) it allows correct subclass behavior: the method produces an instance of the class which received the message.3 instancetype allows the compiler to do more strict typechecking than id.
An illustration of this usage in subclasses from the framework: +[NSString stringWithFormat:] returns an NSString instance, whereas +[NSMutableString stringWithFormat:], returns an instance of the subclass NSMutableString, without NSMutableString being required to explicitly override the method.
As discussed by the [Fundamentals][1] doc, there are other uses for these factory methods, such as accessing a singleton, or appraisal of the necessary memory allocation before it's performed (possible, but less convenient, with a standard alloc/init pair).
1"Static methods" in Java or C++, "class methods" in Objective-C. There's no such thing as static methods in ObjC
2Whereas in an instance method self is, sensibly, a reference to the instance.
3Previously, like the usual initialization methods (initWith...), you would have used id as the return type. Using a specific class name unnecessarily forces subclasses to override the method.
The objects returned from factory methods should be autoreleased, meaning they'll be cleaned up when the associated autorelease pool is drained. This means that you don't own the returned objects unless you copy or retain them. Following is an example of a factory method:
+ (id)myClassWithString:(NSString *)string {
return [[[MyClass alloc] initWithString:string] autorelease];
}
These methods are simply returning an autoreleased version of the object.
+(MyClass*)class
{
MyClass* object = [[MyClass alloc] init];
return [object autorelease];
}
The modern way to do this with ARC and the latest complier is:
+ (instancetype) myClassWithString:(NSString *)string {
return [[MyClass alloc] initWithString:string];
}
No need to autorelease with ARC.
instancetype provides better compile time checks whilst making subclassing possible.

Class methods which create new instances

Apart from the standard [[MyClass alloc] init] pattern, some objects are built from static methods like MyClass *obj = [MyClass classWithString:#"blabla"]
According to widespread memory management guides (including Apple's), you're only responsible for releasing the objects that you alloc.
Can anyone provide me with a template for such methods? How do you return the allocated object ([self alloc]; return self;, perhaps)? How do you make sure that it will be released?
They are class methods, not static methods1. This specific type, creating autoreleased objects, can be referred to as "factory methods" (formerly also "convenience constructors"), and they are discussed in the Concepts in ObjC Guide. They go something like this:
+ (instancetype)whatsisWithThingummy: (Thingummy *)theThingummy {
return [[self alloc] initWithThingummy:theThingummy];
}
Where Whatsis is your class, and Thingummy is another class which your class uses.
If you're not compiling with ARC, the convention is to autorelease the instance before returning it.
The instancetype keyword was introduced by Clang for these kinds of methods; combined with self (which is the class object itself2 in a class method) it allows correct subclass behavior: the method produces an instance of the class which received the message.3 instancetype allows the compiler to do more strict typechecking than id.
An illustration of this usage in subclasses from the framework: +[NSString stringWithFormat:] returns an NSString instance, whereas +[NSMutableString stringWithFormat:], returns an instance of the subclass NSMutableString, without NSMutableString being required to explicitly override the method.
As discussed by the [Fundamentals][1] doc, there are other uses for these factory methods, such as accessing a singleton, or appraisal of the necessary memory allocation before it's performed (possible, but less convenient, with a standard alloc/init pair).
1"Static methods" in Java or C++, "class methods" in Objective-C. There's no such thing as static methods in ObjC
2Whereas in an instance method self is, sensibly, a reference to the instance.
3Previously, like the usual initialization methods (initWith...), you would have used id as the return type. Using a specific class name unnecessarily forces subclasses to override the method.
The objects returned from factory methods should be autoreleased, meaning they'll be cleaned up when the associated autorelease pool is drained. This means that you don't own the returned objects unless you copy or retain them. Following is an example of a factory method:
+ (id)myClassWithString:(NSString *)string {
return [[[MyClass alloc] initWithString:string] autorelease];
}
These methods are simply returning an autoreleased version of the object.
+(MyClass*)class
{
MyClass* object = [[MyClass alloc] init];
return [object autorelease];
}
The modern way to do this with ARC and the latest complier is:
+ (instancetype) myClassWithString:(NSString *)string {
return [[MyClass alloc] initWithString:string];
}
No need to autorelease with ARC.
instancetype provides better compile time checks whilst making subclassing possible.

What do the plus and minus signs mean in Objective-C next to a method?

In Objective-C, I would like to know what the + and - signs next to a method definition mean.
- (void)loadPluginsAtPath:(NSString*)pluginPath errors:(NSArray **)errors;
+ is for a class method and - is for an instance method.
E.g.
// Not actually Apple's code.
#interface NSArray : NSObject {
}
+ (NSArray *)array;
- (id)objectAtIndex:(NSUInteger)index;
#end
// somewhere else:
id myArray = [NSArray array]; // see how the message is sent to NSArray?
id obj = [myArray objectAtIndex:4]; // here the message is sent to myArray
// Btw, in production code one uses "NSArray *myArray" instead of only "id".
There's another question dealing with the difference between class and instance methods.
(+) for class methods and (-) for instance method,
(+) Class methods:-
Are methods which are declared as static. The method can be called without creating an instance of the class. Class methods can only operate on class members and not on instance members as class methods are unaware of instance members. Instance methods of the class can also not be called from within a class method unless they are being called on an instance of that class.
(-) Instance methods:-
On the other hand require an instance of the class to exist before they can be called, so an instance of a class needs to be created by using the new keyword. Instance methods operate on specific instances of classes. Instance methods are not declared as static.
How to create?
#interface CustomClass : NSObject
+ (void)classMethod;
- (void)instanceMethod;
#end
How to use?
[CustomClass classMethod];
CustomClass *classObject = [[CustomClass alloc] init];
[classObject instanceMethod];
+ methods are class methods - that is, methods which do not have access to an instances properties. Used for methods like alloc or helper methods for the class that do not require access to instance variables
- methods are instance methods - relate to a single instance of an object. Usually used for most methods on a class.
See the Language Specification for more detail.
The definitive explanation of this from Apple is here, under the 'Methods and Messaging' section:
https://developer.apple.com/library/mac/referencelibrary/GettingStarted/RoadMapOSX/books/WriteObjective-CCode/WriteObjective-CCode/WriteObjective-CCode.html
In brief:
+ means 'class method'
(method can be called without an instance of the class being instantiated). So you call it like this:
[className classMethod];
- means 'instance method'
You need to instantiate an object first, then you can call the method on the object). You can manually instantiate an object like this:
SomeClass* myInstance = [[SomeClass alloc] init];
(this essentially allocates memory space for the object then initalises the object in that space - an oversimplification but a good way to think about it. You can alloc and init the object seperately but never do this - it can lead to nasty issues related to pointers and memory management)
Then call the instance method:
[myInstance instanceMethod]
An alternative way to get an instance of an object in Objective C is like this:
NSNumber *myNumber = [NSNumber numberWithInt:123];
which is calling the 'numberWithInt' class method of the NSNumber class, which is a 'factory' method (i.e. a method that provides you with a 'ready made instance' of an object).
Objective C also allows the creation of certain object instances directly using special syntax, like in the case of a string like this:
NSString *myStringInstance = #"abc";

Object Makeup, how its constructed?

These are fairly simplistic questions, but something that I wanted to get right in my head before continuing...
#interface BasicTire : NSObject {
}
#end
#interface SnowTire : BasicTire {
}
#end
When you call [SnowTire init] the included [super init] calls [BasicTire init] which in turn calls [NSObject init]? (i.e. a cascade running up to the parent/superclass.
When you [SnowTire alloc] you are creating a single new object, that includes the the functionality of its superClass. Am I right in thinking your not creating multiple objects that are linked in some fashion (i.e. SnowTire > BasicTire > NSObject).
Just wanted to check ...
gary
Yes, normally initializers call superclass initializers. This is done explicitly in the implementation of the init method. While it's possible to call other initializers of the same class or its superclass, it's necessary to make sure that the "designated initializer" always get's called.
If an object does not implement init (or the initializer in question), the one from the superclass is called (like with any other method). This is not seldom, since in Objectve-C instance variables are always initialized to zero (in alloc) and so it's often not necessary to implement a specialized init.
alloc just allocates memory and sets the "isa pointer" of an object which determines an objects class. What you get from it is one uninitialized object (not a linked list) which has room for all of its instance variables (including super classes).
Yes. Each initializer must call the designated initializer for the superclass, all the way up to NSObject. It is also important that each initializer assigns the the result from the super initializer to self. Since an initializer is not required to return the same instance that you send the initialize message to.
Yes. alloc initialized enough memory on the heap for the objects instance variables, and clears this memory with zeros. This way all pointers will be nil, booleans false, etc. And then it sets the isa pointer to the class of the new object.
When you call [SnowTire init] the included [super init] calls [BasicTire init] which in turn calls [NSObject init]? (i.e. a cascade running up to the parent/superclass.
You implement both -[SnowTire init] and -[BasicTire init], so you can just look at your implementations to see that:
Your -[SnowTire init] uses [super init] to call -[BasicTire init].
Your -[BasicTire init] uses [super init] to call -[NSObject init].
[super init] always calls the next available implementation, even if it's not in your immediate superclass. If you don't implement -[BasicTire init], then the [super init] expression in -[SnowTire init] will call -[NSObject init]. That's fine, because you apparently decided that a BasicTire doesn't need any initialization. (If it does, then your omission of -[BasicTire init] was a mistake.)
When you [SnowTire alloc] you are creating a single new object, that includes the the functionality of its superClass. Am I right in thinking your not creating multiple objects that are linked in some fashion (i.e. SnowTire > BasicTire > NSObject).
Yes. Every object has a class (in a variable named isa, as in “this instance is a SnowTire”), and every class has a superclass and a metaclass. -alloc and -init, like all Objective-C methods and C functions, each only return one thing—in this case, one instance with one class.
So, for example, when you send a gripTheSnow message to your snow tire, it uses SnowTire's implementation of that method. If you send a retain message, well, you didn't implement retain in SnowTire and you didn't implement it in BasicTire, so it uses NSObject's implementation. The runtime searches, starting from the object's class (in this example, SnowTire), in a straight line up the class hierarchy, ending at a root class such as NSObject.