Why super doesn't need to get allocated? - objective-c

We always alloc before init in Objective C, then while writing init method, Why we don't alloc a super and then initiate it?
- (id) init {
if(self = [super init]){
//init iVars
}
return self;
}

When the child interface is allocated, its size includes the size of the parent. They aren't separate objects, they're combined. 'super' must be initialized so it can prepare its data members. Your object then initializes its members. For example, lets say you had a custom reference counting interface that needs to initialize 'refCnt' to 1. You then base your interface on that interface. That means your interface's allocation size is the size of the reference counting interface + the size of your specific contributions. (e.g., 'int refCnt' in the reference counting interface and 'int x' in your interface means sizeof(your interface)==8~.) So, the allocation only needs to occur once. Then, you initialize 'super' (the reference counting interface, in this situation) so 'refCnt' will be 1. After that, you initialize your own data.

Because "alloc" already allocates the space for the object you're instantiating.
Your subclass doesn't need to allocate (separate) space for a base class.
You also might find some useful information in this related question.

Related

How does compiler allocate memory for Class Objects?

Given the following variable declaration,
Foo* foo;
how is memory actually being allocated?
This is my guess. There are actually two pieces of memory being allocated here.
A 32 bit number representing a memory address stored at foo [The pointer]. How exactly does the compiler mark or signal that the pointer is actually storing a reference to memory that is of type of Foo?
A contiguous memory segment that is uninitialized and typed as Foo. How does it know how much memory to allocate? How does it mark the memory segment as being of type Foo?
The line of code you've given doesn't allocate any memory. At most, it moves the stack pointer sufficiently to make room for a one-word value (though after optimization, it may not even do that).
A 32 bit number representing a memory address stored at foo [The pointer].
By "32 bit number" I assume you mean "a pointer-sized integer" which is 64 bits on most modern processors. This may, if it's not optimized, be aliased to some location on the stack.
How exactly does the compiler mark or signal that the pointer is actually storing a reference to memory that is of type of Foo?
It doesn't signal this, and it doesn't store a reference to memory that is of any type at all. The above line of code just (at most) makes room for a pointer. In ObjC, at runtime there are no object types. Every pointer to an object is considered id. ObjC absolutely does not promise that this represents a "contiguous memory segment" (there are plenty of cases where what you would think of as "the data" is not contiguous). At a deeper level, the processor does not care about "types" at all. There is just memory and pointers (void *) to memory. (At a deeper level than that, there isn't even "memory." There's physical RAM, caches, registers, and many other things that are generally abstracted away, even in C. For more on that, see C is not a Low-Level Language.)
A contiguous memory segment that is uninitialized and typed as Foo. How does it know how much memory to allocate? How does it mark the memory segment as being of type Foo?
This isn't allocated at all by the above line. If you want to allocate memory for Foo, you must call +[Foo alloc]. Since it is a class method on Foo, it knows how much memory Foo requires. Nothing marks that memory of being of any type, and Objective-C does not actually care what type it is. All it cares is that theres a pointer in the right place called the isa pointer that it can use to lookup how to dispatch messages via objc_msgSend.
There are plenty of cases where something called *Foo does not point to a Foo. It's very common that the actual thing pointed to is a toll-free-bridged type, which is a data structure for a completely different type (a CF structure) that happens to have an isa pointer in the right place so that it can pretend to be an ObjC object. All that is required for the system to work is for things to line up "close enough" that objc_msgSend can function. There is no need (or mechanism) for marking memory as being some particular type.
The size of a pointer like Foo * depends on the target platform. On most current Apple platforms, it is 64-bit, but Apple Watch prior to Series 4 is 32-bit.
There are several contexts in which you might write this:
Foo *foo;
You could write this as a global variable, outside of any #interface or #implementation variable declaration and outside of any function. Then, each time the program is started, it allocates space for one pointer and sets that pointer to nil.
You could write this in an #implementation variable declaration, like this:
#implementation MyObject {
Foo *foo;
}
In this case, you have declared an instance variable (or “ivar”). Each time the program creates an instance of MyObject, the instance includes space for one pointer and sets the pointer to nil.
You could write this as a local variable in a function or a method, like this:
- (void)doSomething {
Foo *foo;
}
In this case, you have declared a local variable. Each time the function or method is called, it allocates one pointer in its stack frame and (assuming you compiled with ARC enabled, which is the default) it initializes the pointer to nil.
Note that in all of these cases, foo does not point to an instance of Foo. It points to nil. To make foo point to an instance of Foo, you must set it to reference to Foo that you got from somewhere else. You could get that reference by calling a function or method, like this:
- (void)doSomething {
Foo *foo;
// foo is nil here.
foo = [[Foo alloc] init];
// If [[Foo alloc] init] succeeded, then foo now points to an
// instance of Foo. If [[Foo alloc] init] returned nil, which
// indicates failure, then foo is still nil.
}
Or you could be passed a Foo reference as a function argument:
- (void)doSomethingWithFoo:(Foo *)incomingFoo {
Foo *foo;
// foo is nil here.
foo = incomingFoo;
// foo now points to whatever incomingFoo points to, which should be
// either an instance of Foo, or nil.
}
Or you could get it from some other global, local, or instance variable.
As to “How exactly does the compiler mark or signal that the pointer is actually storing a reference to memory that is of type of Foo”: It doesn't. At compile-time, the compiler knows that foo should only point to a Foo (or nil), and tries to prevent you from assigning it to things that aren't a pointer to Foo. For example, the compiler will issue a warning or an error for this:
Foo *foo = #"hello";
because the compiler knows that an NSString is not a Foo. (I assume you didn't make Foo a typedef or subclass of NSString.)
However, you can override the compiler's type concerns using a cast:
Foo *foo = (Foo *)#"hello";
or by using the id type:
id something = #"hello";
Foo *foo = something;
This compiles, and it runs fine until you try to do something with foo that an NSString doesn't know how to do.
So it's not the compiler that knows “the pointer is actually storing a reference to memory that is of type of Foo”.
The Objective-C runtime knows that the pointer is actually storing a reference to a Foo. To understand how the runtime tracks the type of an object, you first need to know about the Foo class object.
For every Objective-C class in a program, there is, at runtime, one special object called the “class object”. So for NSObject, there is a single NSObject class object, and for NSString, there is a single NSString class object, and for Foo, there is a single Foo class object. Note that in general, a class object is not an instance of itself! That is, the NSString class object is not itself an instance of NSString, and the Foo class object is not itself an instance of Foo.
The Foo class object knows what makes up an instance of Foo:
The superclass of Foo (maybe NSObject, maybe something else).
The name, type, and size of each instance variable of a Foo (except those inherited from the super class of Foo).
The name, type signature, and implementation address of each message understood by a Foo (except those inherited from the superclass of Foo).
The first bytes of every Objective-C object contain a pointer to a class object.1 This pointer is called the isa pointer, and it determines the type of the object. When you use the syntax that sends a message to an object, like [foo length], the compiler generates a call to objc_msgSend. Recall that in [foo length], the object referenced by foo is called the receiver. The objc_msgSend function uses the isa pointer of the receiver to find the receiver's class object. It looks through the class object's table of messages to find the implementation of length and jumps to it. If Foo doesn't define a length message, then objc_msgSend looks in Foo's superclass for the message, and so on up the superclass chain.2
So, it is this isa pointer that determines the type of the object at runtime.
So how does a Foo object get allocated? When you say [[Foo alloc] init], that means “send the alloc message to the Foo class object, and then send the init message to whatever comes back from alloc”. So the Foo class object receives the alloc message. But the Foo class object probably doesn't implement alloc directly. It inherits the NSObject implementation of alloc.
So +[NSObject alloc] actually allocates the memory for a new Foo. As you say, it allocates a “contiguous memory segment”, but it is not “uninitialized and typed as Foo”. It is initialized and type as Foo. The +[NSObject alloc] documentation says:
The isa instance variable of the new instance is initialized to a data structure that describes the class; memory for all other instance variables is set to 0.
You can look at the implementation here. It's the callAlloc function. It uses the standard C library function calloc to allocate memory, and calloc fills the memory to 0. Then it sets the isa pointer.
As to “How does it know how much memory to allocate”: remember that each class object knows all of the instance variables of its instances. So to allocate a Foo, +[NSObject alloc] sums the sizes of all of the instance variables of a Foo, plus the sizes of all of the instance variables of Foo's superclass, recursively to the end of the superclass chain. That tells it how many bytes to allocate. Except that it would be too slow to do that every time it allocates an object. So the program pre-computes the instance size for every class object at startup, and +[NSObject alloc] looks up the precomputed size of a Foo in the Foo class object.
Unless the object is represented as a tagged pointer, but don't worry about that.
If you want to know what happens when objc_msgSend reaches the end of the superclass chain without finding an implementation, read Objective-C Message Forwarding.

In what circumstances do i need my own initializes to initialize object?

I know objective c has built in 'init' method to initialize object. But i want to know In what circumstances do i need my own initializes to initialize object?
I want to know what value is assigned to self when i invoke 'self = [super init]'
You only need your own initializer when you need your object to default to a state that is different than what the compiler will enforce. That is, all instance variables are initialized to 0 (for integer-like types) or 0.0 (for floating point types). That means all pointers are nil and all numbers are 0(.0). If you need to initialize anything to a different value (creating internal container objects, for example), you need your own initializer.
Similarly, if your class inherits from a class that implements its own initializer, you only need your own if you want your state to be different than the superclass's.

Why would you use a class method constructor versus alloc/init?

There are two choices for constructors in Objective C/Cocoa:
1. Class Constructor
Product *product = [Product productWithIdentifier:#"Chocolate"];
// Use product
2. Alloc/init Constructor
Product *product = [[Product alloc] initWithIdentifier:#"Chocolate"];
// Use product
[product release];
What I do
I tend to use the class method just because it looks cleaner and you don't need a release.
I see a lot of alloc/init - what's the advantage to doing it this way?
My Question
Which one is preferable? Or is it just a matter of taste?
Code
For context, the class Product would have the following:
+(Product *)productWithIdentifier:(NSString *)identifier_ {
return [[[[self class] alloc] initWithIdentifier:identifier] autorelease];
}
-(Product *)initWithIndentifier:(NSString *)identifier_ {
self = [super init]
if (self) {
identifier = identifier_;
}
return self;
}
If you're using ARC, there's not that much of a difference between the two. If you're not using ARC, the difference is extremely important.
The alloc/init combination gives you an owning reference. That means you must release it later on. The classnameWithFoo variant returns a non-owning reference. You may not release it.
This follows the usual Cocoa naming conventions. All methods return non-owning (autoreleased) instances, except for the methods that start with alloc, copy, mutableCopy and new. These return owning references that you must release.
Which one to use is mostly a matter of taste. However, if you need temporary objects that you can dispose quickly the alloc variant results in slightly fewer method calls (the autorelease) and in a loop, it also reduces the maximum memory footprint. However, in most cases this reduced cost is neglectable.
IMO, the biggest difference between the two approaches comes from the fact that using a "class constructor" you get an autoreleased object; this is the most convenient option when you:
assign the allocated object to a retain properties;
when you create "temporary" objects (think of the various NSString methods that build a string from another string: in many case it happens you need to "chain" such calls; the constructor allows you to "forget" about memory management);
when you add the object to some object that retains it (think: addSubview)
In such cases the syntactical advantage of "class constructor" is foremost, but I think it also makes your code "safer" in terms of memory management.
On the other hand, when you create an object to assign it to an assign property (or directly to an ivar for which you have no property), then alloc/init will do perfectly and be preferable to the "constructor" (IMO).
So, in the end, it depends on the way you are going to use the objects you allocate. The class constructor is a convenience method.

Why create custom init when ivars/properties can be set from outside the instance?

I'm reading an Objective-C book and I have a question that the book doesn't seem to really answer.
Let's say I have two custom-made classes.
The first class is called ClassA. It has both the .h and .m files of course. The second class is called ClassB. It also has both .h and .m files.
Somewhere in the code, 'ClassA' has this method:
-(IBAction)displaySomeText:(id)sender {
ClassB *myNumber = [[ClassB alloc]init];
NSString *numberString = [myNumber storedNumberAsString];
// storedNumberAsString is just a method that returns a string object that holds
// myVariable.
[textView insertText:numberString];
//textView is a object I created that just displays some text on screen.
[myNumber release];
}
The book tells me that ClassB should have a method:
-(id)init {
[super init]; //I know why this is done, the book explains it well.
myVariable = 42; // I created this variable already in the ClassB .h file
return self;
}
Now, when in the Interface Builder I click the buttons I connected, etc. It works, the number displayed is 42.
My question is, why do I have to create an -(id)init method for ClassB, if I can do the following in ClassA's method:
-(IBAction)displaySomeText:(id)sender {
ClassB *myNumber = [[ClassB alloc]init];
myNumber.myVariable = 42; //I just do this to skip the -(id)init method.
NSString *numberString = [myNumber storedNumberAsString];
[textView insertText:numberString];
[myNumber release];
}
Doing this, it still displays the same value: 42. I can change it to whatever I like. So why not just use the init inherited from NSObject and just do the simple way myNumber.myVariable = 42?
Suppose that the value of the instance variable were something more complicated than an integer. Suppose it involved reading a string from a file, or getting some information over the network, or just doing some arithmetic. In that case, it wouldn't make sense to have ClassA be responsible for setting that value correctly. That would break the encapsulation that makes it useful to have separate classes in the first place.
In this extremely simple case, you're quite right, there may be no reason to have a custom initializer for ClassB, but in general, a class should itself be responsible for its state being set up correctly. Foisting that responsibility off on other classes means that those others need to know about the internals of the first, meaning the two may be too tightly coupled.
In some cases, the value of the ivar might be a piece of information that is known only to ClassA, or needs to be calculated based on such a piece of information. Then you should create a custom initializer for ClassB which receives that value, e.g., - (id) initWithInteger: This would become the "designated initializer", and you would then override -[ClassB init] to call it with some reasonable default value.
If instances of ClassB do not have to have anything initialized (other than to nil/zero), you do not need to create an explicit init method for ClassB. In this case the question is whether setting myVariable to 42 is ClassB's answer to life, the universe, and everything, or whether myVariable is just a field in ClassB that could be set to any value.
That is, the issue is conceptual, not of physical significance. If conceptually the value 42 "belongs" to ClassB, then there should be an init method for ClassB that sets it. If that specific value has more meaning to ClassA than to ClassB then some method of ClassA should set it. If you do it "wrong" the code still works fine, but your design is slightly less elegant, slightly less extendable, slightly less robust.
This is kind of a tricky issue. I was "brought up" to think that after a constructor (initializer) runs, the object should be ready to go. You should be able to safely call any method on it. Therefore, you need to set up any instance variables in the constructor for which 0 is not a valid value. I like to set them up if they have 0 values anyway, just for sanity, because I never want to bother to know the minute details of every language I work with, like whether they initialize instance variables to 0 automatically.
However, there are some arguments for not initializing some variables.
The initialization is complex, like loading a file or getting data from the network. You want to keep open the possibility of creating an instance and waiting until you're ready to do heavy weight operations.
There are quite a lot of instance variables that are configurable. Your options are to make a constructor with umpteen arguments, or make a constructor with no or a few arguments, and let the caller decide which values should be set to non-default values by property setters.
You need to set up a whole object graph before you can meaningfully initialize a value. That is, initializing the value might have side effects that depend on other related objects. The best solution is to construct each object, then use property setters to set the relationships between objects, then use property setters to initialize attribute values.

+ (void)initialize and memory issues

I'm new to Objective-c and after having read some articles about good practices, it seems that the (void)initialize class method is the best place to initialize my global static variables :
static NSArray *tableCellBackgrounds = nil;
+ (void)initialize
{
if (self == [VariableDisplayViewController class])
{
tableCellBackgrounds = [NSArray arrayWithObjects:
[[UIImage imageNamed:#"ListLine_Pair.png"] stretchableImageWithLeftCapWidth:40 topCapHeight:27],
[[UIImage imageNamed:#"ListLine_Impair.png"] stretchableImageWithLeftCapWidth:40 topCapHeight:27],
nil
];
[tableCellBackgrounds retain];
}
}
My problem now is: when/where should I send a 'release' message?
Thanks...
Well, you don't :)
The memory of your app will get released anyway when closing the application so that is not an issue. There could be an issue however if in your singletons you open file handles which need to be closed on app shutdown.
I do not agree with Joris that you don't need to release these.
Sometimes you allocate rather large static/global tables and data in +(void)initialize that serve all the instances of specific class, but when you release the last instance of that class, you would want to throw these resources away from memory, and not wait for the whole application process to shutdown.
Unfortunately, I haven't found any "+(void)deinitialise" in the ObjC NSObject methods, so the only technique I can suggest is that you also override the class methods
+ (instancetype)allocWithZone:(struct _NSZone *)zone OBJC_SWIFT_UNAVAILABLE("use object initializers instead");
+ (instancetype)alloc OBJC_SWIFT_UNAVAILABLE("use object initializers instead");
- (void)dealloc OBJC_SWIFT_UNAVAILABLE("use 'deinit' to define a de-initializer");
and keep count of your class instances, adding 1 on 'alloc' and 'allocWithZone' and subtracting 1 on 'dealloc'.
Then, when your instance count goes to zero - go on and release those globals you allocated if you want.
Caution though: +(void)initialize won't be called again, when new instance will be created.
More Caution: thread safety should is also important here.
I do not agree with Joris that you don't need to release these.
Your question hints that resources you load as static/global in +(void)deinitialise are for internal use by all the instances of a specific class.
Such resources may have large memory footprint (data blocks needed for special algorithms, tables of constant data, images etc.
When the last instance of this class is released - it makes sense to release the global "class" data, and only load them again when new instances of the class are created.
Obviously, you don't want to wait for the whole application process to shutdown.
Unfortunately, I haven't found any "+(void)deinitialise" in the ObjC NSObject methods, so the technique I can suggest is that you manage this manually.
For that, you need also override the class methods
+ (instancetype)allocWithZone:(struct _NSZone *)zone OBJC_SWIFT_UNAVAILABLE("use object initializers instead");
+ (instancetype)alloc OBJC_SWIFT_UNAVAILABLE("use object initializers instead");
- (void)dealloc OBJC_SWIFT_UNAVAILABLE("use 'deinit' to define a de-initializer");
to keep count of your class instances, adding 1 on 'alloc' and 'allocWithZone' and subtracting 1 on 'dealloc'. (of course call super first).
Then, when your instance count goes to zero - go on and release those globals you allocated if you want.
You can also forget about +(void)initialize and load/initialize your resources when the first instance is created.
A word of Caution: thread safety should is also important here.