user4234
user4234

Reputation: 1527

Using instanceType for return value fails if using self. Why?

static NSMutableDictionary * allTheSingletons;
@implementation BGSuperSingleton

+(instancetype)singleton
{
    return [self singleton1];
}
+(id) singleton1
{
    NSString* className = NSStringFromClass([self class]);

    if (!allTheSingletons)
    {
        allTheSingletons = NSMutableDictionary.dictionary;
    }

    id result = allTheSingletons[className];

    PO(result);
    if (result==nil)
    {
        result = [[[self class] alloc]init];
        allTheSingletons[className]=result;
    }
    return result;
}

BGSuperSingleton should be the parents of all singleton classes.

Then I do in one of the subclass:

+(NSPredicate *)withinASquare:(double)distance{
    CLLocation * anchorWeUsed=[self singleton].mapCenterLocation; //Error map center is not of type ID
    return [self withinASquare:distance fromLocation:anchorWeUsed];
}

It looks like CLANG doesn't understand that singleton is of type +(instancetype) and think the type is id instead.

What am I missing?

Replacing self with the MySubSingletonClass (which is something that's known at compile time) works though.

Any explanation?

Upvotes: 2

Views: 510

Answers (1)

MANIAK_dobrii
MANIAK_dobrii

Reputation: 6032

Not sure (and all the beneath are only my assumptions) but seems that at compile time compiler does not know the class of [self singleton1]. As it's said in docs (if we extrapolate that behavior on instancetype also):

... and the method will have a related result type if its return type is compatible with the type of its class...

I.e. singleton1 returns object of an unknown class and singleton as well considers that it returns object of incompatible to BGSuperSingleton class (as far as it's unknown at compile time), thus related result magic is not working here.

Was interested in that and also checked:

+ (NSPredicate*) withinASquare: (double)distance {
    CLLocation* anchorWeUsed = [[self alloc] init].mapCenterLocation; // Error map center is not of type ID
    return [self withinASquare:distance fromLocation:anchorWeUsed];
}

alloc and init return related result class and the error is still there. The thing helped was:

+ (NSPredicate*) withinASquare: (double)distance {
    BGSuperSingleton* bgSuperSingleton = [[self alloc] init]; // class is known at compile time
    CLLocation* anchorWeUsed = bgSuperSingleton.mapCenterLocation; // no error here
    return [self withinASquare:distance fromLocation:anchorWeUsed];
}

I'm still interested in this and hope somebody could approve or correct my assumptions.

Upvotes: 1

Related Questions