Objective-C supports a special type called `instancetype that can only be used as type returned by a method. It evaluates to the class of the receiving object.
Consider the following class hierarchy:
@interface Foo : NSObject
- (instancetype)initWithString:(NSString *)string;
@end
@interface Bar : Foo
@end
When [[Foo alloc] initWithString:@"abc"]
is called, the compiler can infer that the return type is Foo *
. The Bar
class derived from Foo
but did not override the declaration of the initializer. Yet, thanks to instancetype
, the compiler can infer that [[Bar alloc] initWithString:@"xyz"]
returns a value of type Bar *
.
Consider the return type of -[Foo initWithString:]
being Foo *
instead: if you would call [[Bar alloc] initWithString:]
, the compiler would infer that a Foo *
is returned, not a Bar *
as is the intention of the developer. The instancetype
solved this issue.
Before the introduction of instancetype
, initializers, static methods like singleton accessors and other methods that want to return an instance of the receiving class needed to return an id
. The problem is that id
means "an object of any type". The compiler is thus not able to detect that NSString *wrong = [[Foo alloc] initWithString:@"abc"];
is assigning to a variable with an incorrect type.
Due to this issue, initializers should always use instancetype
instead of id
as the return value.