Quick example of calling a method that doesn't take any arguments and returns an object:
id foo = [self bar];
is the same as:
id foo = self.bar;
which is also the same as:
id foo = [self performSelector:@selector(bar)];
or:
IMP barImp = [self methodForSelector:@selector(bar)];
id foo = barImp(self, @selector(bar); [1]
and finally:
id foo = ((id)(id, SEL)objc_msgSend)(self, @selector(bar)); [2, 3, 4]
1. Because we're calling the IMP, or implementation, directly, we don't need a cast (like we do below, with objc_msgSend).
2. Casting the function is optional, but, helps to prevent things like endian differences and your return value getting mangled when using the same code on PPC and Intel. Not too big of a deal anymore.
3. There are actually two other varieties of objc_msgSend, depending on your return type — specifically, floating point calls should use objc_msgSend_fpret and calls that return a struct should use objc_msgSend_stret.
4. I hope I got this cast right, I didn't try to compile it.