Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can dot syntax not be used on a method whose return type is instancetype?

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.

like image 609
Reid Main Avatar asked Apr 04 '14 14:04

Reid Main


2 Answers

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.

like image 195
tapi Avatar answered Nov 18 '22 18:11

tapi


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.

like image 1
matt Avatar answered Nov 18 '22 16:11

matt