Objective-C: Self-variable understanding Issues - objective-c

I want to know some features about self.
Which context have self variable in class method?
Why self.self allowed in init method?
First:
We have a class ExampleClass
#interface ExampleClass:NSObject
#property (nonatomic,strong) NSString* a;
+(ExampleClass*)createExampleClass;
#end
#implementation ExampleClass
-(id)init{
self = [super init];
if(self){
[self.self init]; #Allowed
[self init]; #Not Allowed ?
}
}
+(ExampleClass*)createExampleClass{
/*do work here*/
NSLog(#"Self: %# \n Class: %#",self,[self class]);
}
#end
In this example we will see something like this:
Self: ExampleClass
Class: ExampleClass
But why?!
And in init method [self.self init] allowed, but not allowed '[self init]'.
Why does this happen?

In a class method, self is the class. For classes [self class] simply returns self, so self and [self class] are basically the same thing there.
Calling [self init] in the init method doesn't make any sense, it would cause an infinite recursion. However, the compiler error you get is a restriction of ARC, if you'd use self = [self init], the error would go away, but it would still make no sense. You might do this in a different initializer method though, to call the designated initializer.

self.self is short for [self self] which does nothing but return self.

self in class method is the class object itself.
NSObject has self method which returns itself.
    See here:  https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Protocols/NSObject_Protocol/Reference/NSObject.html#//apple_ref/occ/intfm/NSObject/self
Self: ExampleClass // Name of the class.
Class: ExampleClass // Name of the meta-class object which is same with class object.
If you print pointer address, you will see two objects are different.
Here's nice illustration and description.
http://www.sealiesoftware.com/blog/archive/2009/04/14/objc_explain_Classes_and_metaclasses.html

self.self.self.self.self.self is also valid :) or [[self self].self self].self.self

Related

Return object of [super Init]

Well...I have read and have done a lot of research on the expression of [super init] in class inheritance of objective-c. Even some of the questions have been well explained and answered on stackoverflow. However, I still don't really understand how inheritance or the [super init] works.
In other languages, the superclass knows nothing about the subclass. There is no way for the superclass to return an object of the subclass because the superclass has no knowledge of the subclass. So my question is if expression self = [super init] return the object of the SUPERCLASS or SUBCLASS. Here I do know that the [super init] could return another object or nil, which makes sense. But assuming everything works fine and neither is it nil nor return another object. If it returns a regular object, does it return the object of the superclass or derived class, which is the class in which this self = [super init] is defined. If it returns an object of the super class, then it makes sense but then since as we know, the object of the superclass knows nothing about the subclass, how can it access the members (fields, messages or methods) of the subclass. If it returns an object of the subclass, then it does not make sense, since there is no way that the superclass can return an object of the derived class because the superclass knows nothing of it.
This is one of the aspects that is really confusing for those who transition from other languages to objective-C.
self = [super init]
will return the object from the superclass. However, note that the object itself has likely been allocated using alloc on your current class.
Consider the following:
#interface A : NSObject
- (instancetype)init;
#end
#interface B : A
- (instancetype)init;
#end
#implementation B
- (instancetype)init {
self = [super init];
if (self) {
// Do initialization for B
}
return self;
}
#end
When you create a new object of a class B you do as follows:
B *obj = [[B alloc] init];
In turn the following happens:
[B alloc]allocates the object with enough space to hold all of B.
Calls init on the newly created object of class B.
Then init on class A is called from B's init method
init on class A will* return the object allocated with B's alloc.
*) Note that the init method may return another object than the allocated one. This is allowed, and is a reason why you usually should assign the result to self.
Read more - What does it mean when you assign [super init] to self?

Initializing objects using Objective-C, clarification needed

if header file declares
#interface SomeClass: NSObject {
Data* d;
}
#property (nonatomic, retain) Data* d;
Why is the following line in the implementation file giving me a warning (and init method does not get called?)
[[[self d] alloc] init];
The warning i get is
Instance method '-alloc' not found (return type defaults to 'id')
Meanwhile, Data has
- (id) init method, that is not being called.
Please help me understand why.
alloc should be invoked on a class, not on an instance.
interface SomeClass : NSObject
{
Data *d;
}
Declare an init method on SomeClass and make it look like:
- (id) init
{
self = [super init];
if (self)
{
d = [[Data alloc] init];
}
return self;
}
- (void) dealloc
{
[d release];
[super dealloc];
}
Now you do:
SomeClass *c = [[SomeClass init] alloc];
And you can use the class. Note that you should probably read a little more on classes and objects and about memory management too (when you should release c, etc.).
If, by any chance, you have the possibility to use ARC (automatic reference counting), you won't need to take care of releasing stuff. But that doesn't come with Xcode 4.1, only with 4.2 which is not publicly accessible, apparently.
The problem isn't -(id)init, it's -(id)alloc. alloc is a class method of NSObject, which means you send it to the class itself and not to an instance of that class, i.e.:
[Data alloc]; // Correct
[someDataInstance alloc]; // Method not found
When you call [self d], you're given an instance of a Data, which you're then sending a -(id)alloc message to. Since NSObject doesn't have a -(id)alloc (only a +(id)alloc), you get the warning.
You should be doing
self.d = [[Data alloc] init];
As Matt says, alloc is a class method, and must be called on the class itself.

objective c help - calling methods?

Hey,
I am new to programming I wanted to know why is it always [self method];? I mean why is it that way could someone explain me why is it self and what is going on in the background? sorry if it is a stupid question
thanks,
TC
Basically, what self refers to is the object that you're currently in the context of. [self somemethod] means that you're invoking a method named somemethod in the class that self was initialized as.
For example, if you were to do something like this:
Foo *f = [[Foo alloc]init];
[f someMethod];
You'd be invoking someMethod on the Foo instance.
But if you're working inside of the class Foo, self serves as an explicit reference to the current object. In this case, you'd simply use [self someMethod] to invoke someMethod.
-(id) init {
if (self = [super init]) {
[self someMethod];
}
...
}
-(void) someMethod { }
Does that help?
[self method] calls the method of the calling class. For example, in the header file of your class,
#interface YourClass : NSObject {
}
- (void) myMethod;
then, you can call the 'myMethod' in YourClass by using [self myMethod]. Does it make sense?
During calling [self method], there is no any background working. [self method] is almost same the calling function in C. When you use [self method], 'method' in your class is just called right away.
Because [self method]; calls the -method method in the class from which it is called.
If you want kill John in ObjC:
[john sendBullet]
if you do sendBullet to myself (shortly self), it's a suicide
[self sendBullet]
got the difference? :)

Objective C init

Disclaimer, I'm new to Objective C. But I can't find this explained. I've seen two ways of implementing init:
- (id)init {
if ([super init]) {
return self;
} else {
return nil;
}
}
and
- (id)init {
if (self = [super init]) {
// do your init business here
}
return self;
}
so let's say i have:
myObj = [[MyObject alloc] init];
where MyObject class is a subclass of NSObject. in the second example, does init not return an initialized version of NSObject? so myObj would ... how would it know what it is? wouldn't it think it was an NSObject rather than a MyObject?
1) First version is just wrong. self should be always assigned with value returned by super initializer, because init<...> of super can return another object upon initialization (it's not unusual BTW). Second version is actually an 'official' way to implement init<...> methods.
2) 'wouldn't it think it was an NSObject rather than a MyObject'. myObj is instance of 'NSObject' and instance of 'MyObject'. It's the whole point of inheritance.
i just want to know, under the hood, how it does it.
It's pretty simple. 99.9% of all the classes you'll ever write will inherit from NSObject in some fashion. In the initializers, you're supposed to invoke super's designated initializer and assign it to self. Eventually, [super init] will be invoking -[NSObject init]. According to the documentation, that's implemented like this:
- (id)init {
return self;
}
So technically, if you inherit directly from NSObject, you're probably safe to not do the assignation of self = [super init];, because you know (and you're guaranteed) that this is equivalent to: self = self;, which is kind of pointless. Regardless, you should leave it in for consistency's sake.
However, once you start getting further down the inheritance chain, and especially when you're inheriting from opaque classes (ie, a class whose .m file you do not have), then things start getting shady. It is possible that you'll come across a class whose designated initializer looks something like this:
- (id) initWithFoo:(id)aFoo {
if ([aFoo isSuperFast]) {
[self release];
return [[SuperFastFooWrapper alloc] initWithFoo:aFoo];
}
self = [super init];
if (self) {
_foo = [aFoo retain];
}
}
This isn't as common, but it does happen. In this case, we're destroying self ([self release], to balance the alloc call that immediately preceded this) and instead returning a different object.

custom class = custom +alloc , custom +init

I'm new with objective c for the iphone.
I'm writing a custom class, then, should I write my own +alloc, +init methods?
I believe that: the +alloc will just call [thing alloc]; and the +init will perform something like: [thing setValue:X];
is there a "default" +alloc and +init methods?
if yes, what should I wait for the default +alloc and +init?, let's say i have a NSMutableDictionary*
i.e.
#interface class1 : NSObject {
NSString *test;
NSMutableDictionary *map;
}
thanks
You generally don't need to write your own +alloc method.
For your example, you might have an -init that looks like:
- (id)init {
self = [super init];
if (self) {
map = [[NSMutableDictionary dictionary] retain];
}
return self;
}
Note that you first call the superclass -init, and check that it worked, before initializing your own variables.
You should NEVER override alloc.
As for init, which is an instance method, by the way, yes that would be the place where you'd probably want to set up your variables.