What does self mean in Objective-C? When and where should I use it?
Is it similar to this in Java?
self refers to the instance of the current class that you are working in, and yes, it is analagous to this in Java.
You use it if you want to perform an operation on the current instance of that class. For example, if you are writing an instance method on a class, and you want to call a method on that same instance to do something or retrieve some data, you would use self:
int value = [self returnSomeInteger];
This is also often used for accessor methods on an instance (i.e. setters and getters) especially with setter methods, if they implement extra functionality rather than just setting the value of an instance variable, so that you do not have to repeat that code over and over when you want to set the value of that variable, for example:
[self setSomeVariable:newValue];
One of the most common uses of self is during initialization of a class. Sample code might look like:
- (id)init
{
self = [super init];
if(self!=nil) {
//Do stuff, such as initializing instance variables
}
return self;
}
This invokes the superclass's (via super) initializer, which is how chained initialization occurs up the class hierarchy. The returned value is then set to self, however, because the superclass's initializer could return a different object than the superclass.
self is an implied argument to all Obj-C methods that contains a pointer to the current object in instance methods, and a pointer to the current class in class methods.
Another implied argument is _cmd, which is the selector that was sent to the method.
Please be aware that you only get self and _cmd in Obj-C methods. If you declare a C(++) method, for instance as a callback from some C library, you won't get self or cmd.
For more information, see the Using Hidden Arguments section of the Objective-C Runtime Programming guide.
Yes, it's exactly the same as "this" in Java - it points to the "current" object.
Two important notes:
The class itself, e.g. UIView (I'm NOT talking about a UIView object) is itself an object, and there is a self associated with it. So for example, you can reference self in a class method like this:
// This works
+(void) showYourself { [self performSelector: #selector(makeTheMostOfYourself)]; }
// Class method!
+(void) makeTheMostOfYourself { }
Note that the compiler does NOT raise any warnings or errors, even if the self you mean to reference is an object and not a class. It is VERY easy to cause crashes this way, for example:
// This will crash!
+(void) showYourself { [self performSelector: #selector(makeTheMostOfYourself)]; }
// Object method!
-(void) makeTheMostOfYourself { }
// This will crash too!
-(void) showYourself2 { [self performSelector: #selector(makeTheMostOfYourself2)]; }
// Class method!
+(void) makeTheMostOfYourself2 { }
Sadly, this makes class methods a bit harder to use, which is unfortunate because they are a valuable tool for encapsulation through information hiding. Just be careful.
Wow, that many half-correct answers and misleading hints. This let me answer the Q even there is a accepted answer for years:
First of all: It is really hard to compare a concept of messaging/calling in the context of an early binding, static typing language as Java with a late binding, dynamically typing languages as Objective-C. At one point this will break. I would say: No, this is not similiar, since the typing and dispatching concepts of both language are fundamental different so nothing can be similar to the other one. However, …
Then we should differ between the "two sides" of self.
A. Using self
When you use it in a message, it is simply an object reference as any other:
[self doSomething];
[anotherObject doSomething];
Technically both lines works identically (accept of having a different receiver, of course). This especially means, that the first line does not lead to an execution of a method inside the class of self, because self does not necessarily refer to "that class". As every message inside Objective-C (single exception: messages to super)this can lead to the execution of a method in a subclass:
#interface A : NSObject
- (void)doSomething;
- (void)doAnotherThing;
#end
#implementation
- (void)doSomething
{
[self doAntoherThing];
}
- (void)doAnotherThing
{
NSLog( #"A" );
}
#interface B : A
- (void)doSomething; // Not necessary, simply as a marker
#end
#implementation B
- (void)doAnotherThing
{
NSLog( #"B" );
}
In a code like this
B *b = [B new;]
[b doSomething];
The line
[self doAnotherThing];
in class A will lead to the execution of -doAnotherThing (B), because messages to self are late bound as every other message. The result on the console will b "B", not "A". Using self as a receiver you should not think of a single special rule. There is completely none.
(And the above example is a very good example for using self in class methods, because the same situation can occur on class methods. Using the class itself breaks polymorphism, what is one of the worst idea at all in OOP. DO use self in class methods, too.)
B. Getting self
What is self pointing to? It points to the object to whom the message is sent that caused the execution of the current method.
Having …
…[someObject doSomething]… // some object is a reference to an instance object
… as a message, a method is called, in the most simple case …
- (void)doSomething
{ … }
In such a case, self can point to an instance of the class, the method belongs to. And it can point to an instance of a subclass, the method belongs to, too. You don't know. (And this information is preserved using self to send a message as explained above.)
If the message is sent to a class object, self points to the class object, that was the receiver of the message. This is completely analogous. Therefore it is possible that self points to a subclass object:
#interface A : NSObject
+ (void)doSomething;
+ (void)doAnotherThing;
#end
#implementation
+ (void)doSomething
{
[self doAntoherThing];
}
+ (void)doAnotherThing
{
NSLog( #"A" );
}
#interface B : A
- (void)doSomething; // Not necessary, simply as a marker
#end
#implementation B
+ (void)doAnotherThing
{
NSLog( #"B" );
}
Having this classes
…[A doSomething]…
self inside -doSomething (A) points to the class object of B. Therefore [self doAnotherThing] of B(!) is executed. This is clearly different from
+ (void)doSomething
{
[A doAntoherThing];
}
The latter version causes relevant harm to the principles of OOP.
As a side note it is possible that self inside a class method of a root class points to an instance object of the root class or any subclass. You have to keep this in mind, when writing categories on NSObject.
self is an object pointer to the current instances dispatch table. It is an implicit first argument to every member function of an object, and is assigned when that function is called.
In functions like init, you need to be careful that when you call the super class init you reassign self to be the return value as the super class init may redefine what self points to.
super is similar to self except it points to the superclass dispatch table.
I have following API in Objective C declared in protocol:
-(id)decodeData:(NSData *)data inType:(Class)className error:(NSError **)error;
Now, I have implemented a class in Swift that implements ObjC protocol as below:
#objc class XMLDeserializer: NSObject, IDeserializer {
#objc func decodeData(data: NSData!, inType className: AnyClass!) throws -> AnyObject {
}
}
Now, my Swift class method is called from within the Objective C class as a part of protocol method calling. But, it is NOT Called.
What could be the reason?
Update:
I have my Communicator class where I have the serializer property in it. When I give my custom serializer object to that property, it is expected that it will call the protocol method (when the success response will come) as described above.
From my communicator class, below is the code how I call my protocol method:
responseObject = [self.responseSerializer decodeData:dataToDeserialize inType:self.responseType error:&err];
I have checked and printed the output in console from NSData in Comms Class, to verify that I am getting the successful response.
Only concern is that, my custom serializer is plugged into communicator and then also, my protocol method is not getting called.
I found similar question: LINK but that didn't solved my problem because passing MyClass.self will append the module name in that argument.
Let me know if more information is needed.
I'm still new to Objective-C (coming from a Java and C# background), and I'm implementing a plugin system for an iOS SDK I'm developing.
I've defined my plugin header (Plugin.h) as follows (the java counterpath would be an abstract class, correct me if I'm doing anything wrong here).
#protocol Plugin <NSObject>
#required
- (void)initialize;
- (NSString *) getPluginName;
- (NSString *) getVersion;
#end
I then have a method in my SDK that can be used to register plugins. The array will be an array of objects that inherit from TFTPlugin.
+ (void)registerPlugins:(NSMutableArray*) array
{
for(Plugin *plugin in array)
{
[pluginClasses addObject:plugin];
}
}
But I'm getting an error at the for loop: Use of undeclared identifier 'plugin'.
Any idea what I'm doing wrong here?
Thanks
Try this:
for(id plugin in array){
if([[plugin class] conformsToProtocol:#protocol(Plugin)]) {
[pluginClasses addObject:plugin];
}
}
The checking to see if it conforms to the protocol is optional if you know that everything you are passing in actually does.
I want to know the value of "_lastNotificationReceivedBundleIdentifier" which is an instance variable of a class. The header is dumped from iOS springboard app.
#interface SBRemoteNotificationServer : NSObject <APSConnectionDelegate> {
NSMutableDictionary* _bundleIdentifiersToClients;
NSMutableDictionary* _environmentsToConnections;
unsigned _lastPlayedAlertSound;
NSString* _lastNotificationReceivedBundleIdentifier;
}
but the following code does not work:
%hook SBRemoteNotificationServer
-(void)noteApplicationFinishedLaunching:(id)launching{
NSLog(#"identifier=%#",_lastNotificationReceivedBundleIdentifier);
%orig;
}
%end
and the compiler error is:
error: ‘_lastNotificationReceivedBundleIdentifier’ was not declared in this scope
How do I access and log this NSString?
You could probably use the objective-c runtime capabilities and take a look at the method object_getInstanceVariable(the_object, "_lastNotificationReceivedBundleIdentifier", (void**)&yourPointer);
Another solution to try is:
[self valueForKey:#"lastNotificationReceivedBundleIdentifier"];
where self is the parent object and lastNotificationReceivedBundleIdentifier is the variable name. eg same as self.lastNotificationReceivedBundleIdentifier.
Using Xcode.
In this code (func is declared in interface), tells subj error, standing on string with 'self'.
+ (void) run: (Action) action after: (int) seconds
{
[self run:action after:seconds repeat:NO];
}
What the... ?
self is an instance variable used to refer to an instance of the current object.
You are attempting to use it in a class level method +(void)... where self has no meaning. Try using a shared instance, or passing an instance of the class in question to the method.
+ (void) run:(Action)action on:(MyClass*) instance after:(int) seconds
{
[instance run:action after:seconds repeat:NO];
}
EDIT
My commenters have pointed out that self does have meaning in class level contexts, but it refers to the class itself. That would mean you were trying to call a method that looks like this:
[MyClass run:action after:seconds repeat:NO];
Where you should be aiming for:
[myClassInstance run:action after:seconds repeat:NO];