self is not hard to understand if you keep the following facts in mind.
All methods operate on an object.
Every method (except init… methods) of a class has a hidden argument named self, which points to the object the method operates on.
Here are the three key facts you should know about self:
-
In a class method, self points to the class object; there is only one class object.
-
In an instance method, self points to an object, that is, an instance of the class; there can be many instances.
-
An object can send itself a message by simply sending the message to self.
Look at the following all-in-one example:
// main.m
#import <Foundation/Foundation.h>
// A simple class
@interface FooBar : NSObject
- (instancetype)initWithName:(NSString *)name;
+ (void)paintWhite;
- (void)paintGreen;
- (void)paintYellow;
- (void)paintWhatever;
@end
int main (int argc, const char * argv[])
{
@autoreleasepool {
FooBar *fooBar1 = [[FooBar alloc] initWithName:@"fooBar1"];
FooBar *fooBar2 = [[FooBar alloc] initWithName:@"fooBar2"];
FooBar *fooBar3 = [[FooBar alloc] initWithName:@"fooBar3"];
// Print the address of the class object and paint it...
printf ("%s: class_obj = %p\n", __func__, [FooBar class]);
[FooBar paintWhite];
printf ("\n");
// Print the address of fooBar1 and paint it...
printf ("%s: fooBar1 = %p class_obj = %p\n", __func__, fooBar1, [FooBar class]);
[fooBar1 paintGreen];
printf ("\n");
// Print the address of fooBar2 and paint it...
printf ("%s: fooBar2 = %p class_obj = %p\n", __func__, fooBar2, [FooBar class]);
[fooBar2 paintYellow];
printf ("\n");
// Print the address of fooBar3 and paint it...
printf ("%s: fooBar3 = %p class_obj = %p\n", __func__, fooBar3, [FooBar class]);
[fooBar3 paintYellow];
printf ("\n");
// Get it to send a message to itself...
[fooBar3 paintWhatever];
printf ("\n");
}
return 0;
}
@implementation FooBar
{
NSString *_name;
}
- (instancetype)initWithName:(NSString *)name
{
self = [super init];
if (self) {
_name = [name copy];
}
return self;
}
+ (void)paintWhite
{
printf ("%s: self = %p class_obj = %p\n", __func__, self, [FooBar class]);
}
- (void)paintGreen
{
printf ("%s: %s self = %p class_obj = %p\n", __func__, _name.UTF8String, self, [FooBar class]);
}
- (void)paintYellow
{
printf ("%s: %s self = %p class_obj = %p\n", __func__, _name.UTF8String, self, [FooBar class]);
}
- (void)paintWhatever
{
printf ("%s: %s self = %p class_obj = %p\n", __func__, _name.UTF8String, self, [FooBar class]);
[self paintGreen];
}
@end
If you build and run the above example, you should see output that looks like this:
main: class_obj = 0x100002220
+[FooBar paintWhite]: self = 0x100002220 class_obj = 0x100002220
main: fooBar1 = 0x1001096d0 class_obj = 0x100002220
-[FooBar paintGreen]: fooBar1 self = 0x1001096d0 class_obj = 0x100002220
main: fooBar2 = 0x1001096e0 class_obj = 0x100002220
-[FooBar paintYellow]: fooBar2 self = 0x1001096e0 class_obj = 0x100002220
main: fooBar3 = 0x10010a770 class_obj = 0x100002220
-[FooBar paintYellow]: fooBar3 self = 0x10010a770 class_obj = 0x100002220
-[FooBar paintWhatever]: fooBar3 self = 0x10010a770 class_obj = 0x100002220
-[FooBar paintGreen]: fooBar3 self = 0x10010a770 class_obj = 0x100002220
Now you should carefully examine the above output and spot those three key facts about self.
[Accelerate your learning and become a competent programmer faster than you can imagine: pretty-function.org]