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.
For any object created I generally use two two scopes 1) Singleton 2) {local scope}. I am looking for something in between.
Say I have one object that 5 view controllers are editing. I want to share an object between view controllers without having to pass it between view controllers. But it should not also live throughout application since once I am done editing the object i don't need it anymore.
I don't want to inherit all view controller from another class an create a variable there. Since view controller are reusable for different objects. I want to create an object that comes to life before launch of first view controller, lives throughout the scope of 5 view controllers and then dies after I have saved it someway. Is there anyways I could do this in iOS.
An alternative is to use your AppDelegate. Within it you can declare a global var than 2 functions, a first one to get the current value and another one to set the value.
It might give something like this:
// Get AppDelegate instance
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate;
// Use your getter to get the current value
var something = appDelegate.getYourStuff();
// Or use a setter to set it, a modifier to modify oit
appDelegate.setYourStuff(yourStuff);
appDelegate.modifiyYourStuffAttribute(newAttributeValue);
Don't realize if such a method is a bad practice or not, but it works for me.
Open to other suggestions!
As Mat said you can do is in that what. For me better is to create specific class for that that will do one particular job.
class EditingSession {
class Factory {
private static let session = EditingSession() //do it lazy
static func create() -> EditingSession {
return session
}
}
func openSession() {
}
func endSession {
}
func getData () -> AnyObject {
...
}
}
In editing session create private initializer. Factory should give the shared instance.
You can pass this class to your ViewControllers and manipulate with the data. You can inject it or just set as property in your VC or VM.
If you are done with editing you should end session and clear data or other stuff.
So in a regular Class, you can override the setter method for a class property:
-(void)setSortBy:(NSString *)sortBy {
// Do other stuff
_sortBy = sortBy;
}
using the _ prevents an infinite loop of the method calling its self.
I am trying to do something similar with a NSManagedObject class, but it does not give the option to use the underscore (_):
-(void)setHasNewData:(NSNumber *)hasNewData {
// update self.modifiyDate
_hasNewData = hasNewData;
}
Gives me an error and suggests I replace _hasNewData to hasNewData.
Is this how it should be done or will it give me an infinite loop?
I want it to update the NSManagedObject's property modifyDate anytime I set hasNewData.
Your first example for a "regular class" works if _sortBy is the instance variable
backing up the sortBy property (e.g. the default synthesized instance variable for
that property).
But Core Data properties are not backed up by instance variables.
When overriding Core Data accessors, you have to use the "primitive accessors",
and also trigger the Key-Value Observing notifications:
-(void)setHasNewData:(NSNumber *)hasNewData {
[self willChangeValueForKey:#"hasNewData"];
[self setPrimitiveValue:hasNewData forKey:#"hasNewData"];
[self didChangeValueForKey:#"hasNewData"];
// do other things, e.g.
self.modifyDate = ...;
}
More examples can be found in the "Core Data Programming Guide".
I am trying to pass a reference of my current NSObject Class through two other object classes so I can access the current initialization of the original NSObject class I called from.
I will try to outline why I am doing this in as simply as possible. I have 3 NSObject Classes and an appDelegate.
AppDelegate
RemoteSites
EngineRequest
EngineReasponse
This is the logical flow of the app as it stands
Appdelegate.m
calls RemoteSites method "GetRemoteSites" this method reutrns a BOOL for confirmation
RemoteSites.m
-(BOOL)GetRemoteSites {
// calls EngineRequests method like so
EngineRequests *engineRequests = [[EngineRequests alloc] init];
[engineRequests GetRemoteSites:self];
//..
}
EngineRequests.m
- (void)GetRemoteSites:(NSObject *)myObjectClass {
// get everything ready to send off request
}
send off request then return recived data + NSObject refrence to EngineReasponse
EngineReasponse.m
- (void)GetRemoteSites:(NSData *)receivedData Object:(NSObject *)requestingClass
{
// pass requestingClass to a NSObject var that will later be used to pass the data back to the original class that started the request
requestingClassObject = requestingClass
}
//..
[requestingClassObject GetRemoteSitesNow:reducedDataPacket]; // GetremoteSitesNow is a method inside RemoteSites class, however using requestingClassObject I cannot see any of the classMethods my class has in it
//..
So thats the overall flow of the process I am trying to complete, the whole point is to try and get -(BOOL)GetRemoteSites to return Yes to the AppDelegate.
In summery my question stands as this. Why can I not access RemoteSites methods from EngineReasponse's, I have passed the class Object refrence correctly I think but for some reason I cannot access the methods.
Any help solving my issue would be greatly appreciated.
EngineRequests.m
- (void)GetRemoteSites:(id)remoteSites {
// create your class object here or globally.
RemoteSites *remotesite = (RemoteSites*)remoteSites
}
EngineReasponse.m
- (void)GetRemoteSites:(NSData *)receivedData Object:(id)requestingClass
{
RemoteSites *requestingClassObject = (RemoteSites*)requestingClass
}
//
[requestingClassObject GetRemoteSitesNow:reducedDataPacket];
//
Sorry for the typo. Hope it will help.
I've added a view controller as child like this:
UIViewController *sendViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"send"];
[self addChildViewController:sendViewController];
In the sendViewController I got this property:
#property (strong, nonatomic) IBOutlet StringInputTableViewCell *nameCell;
and in that class I can do something like self.nameCell.textField.text = #"test"; to set the textField to test
But how can I get this text thats filled in the textField in the parent class?
You are mixing model and view, thus breaking the MVC design pattern.
You should not try to read what is the content of a UI element. Rather you should have all the data (i.e. model) and the view (i.e. the UI, such as text fields) managed by a controller.
There are (easy) ways to get to this information, but I strongly advise you not to go down that road!
Basic inheritance between the parent and child class should allow you to pass the property forward.
You'll need to create a child object of the class say obj. Then to get the text value of the field you'll use (in the parent class)
id obj = [[ChildClassName alloc] init];
NSString *myChildsText = obj.nameCell.textField.text; // will get the value #"test" as assigned in the childclass.
Or of course, you can create a getter and setter in the Child Class for your #property. For example ::
- (IBOutlet)nameCell {
// returns the value
}
- (IBOutlet)setNameCell :(StringInputTableViewCell)newValue {
//set the value to the #synth value here…
}
then you can call the child objects getters/setters as below ::
NSString *text = [obj nameCell]; //etc etc
You can use 4 approaches in here
a) keep reference to you childviewcontroller -> get the value directly
b) use delegate method ( best for observing changes in your textfield )
c) send NSNotification -> this comes with overhead, well at certain points it can help you a lot
d) KVO