Pretend I have a category on NSObject that defines the following method:
+ (instancetype)allocTemplate
{
id instance = [self new];
return instance;
}
and I have the following class:
@interface FDActor : NSObject
@property (nonatomic, copy) NSString *name;
+ (void)sayHi;
@end
@implementation FDActor
+ (void)sayHi
{
[self allocTemplate].name;
}
@end
How come [self allocTemplate].name
errors out at compile time if self is FDActor?
I am aware it works if you use normal message sending syntax but I am explicitly interested in the dot syntax error.
It would appear as though instancetype is used only for type checking during assignment, so
FDActor *actor = [FDActor allocTemplate]
would not produce a warning.
If we cast the return type of allocTemplate the problem goes away.
- (void)sayHi
{
((__typeof__(self))[[self class] allocTemplate]).name;
}
But note that this only works in an instance method since the typeof an instance is another instance. Note also that since we now explicitly type the return value the allocTemplate method is no longer necessary, if all were looking for is type checking then we can even just cast nil and it will work.
If we try the same thing in a class method it doesn't work
+ (void)sayHi
{
((__typeof__(self) *)[self allocTemplate]).name;
}
This is because (__typeof__(self) *)
doers not evaluate to FDActor *
but Class *
which ARC will complain about. It looks like there is no way to resolve the type information FDActor *
in a generic way from within a class method at compile time.
I rather expected the instancetype
keyword to be a little more useful.
The error message tells you. [self allocTemplate]
is an id
. Property syntax never works on id
.
Note that this does work:
[FDActor allocTemplate].name;
I think the class to which instancetype
is to be related must be specified in the call; otherwise we just fall back on id
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With