Skip to content

Instantly share code, notes, and snippets.

@danhd123
Created June 23, 2013 08:42
Show Gist options
  • Save danhd123/5844319 to your computer and use it in GitHub Desktop.
Save danhd123/5844319 to your computer and use it in GitHub Desktop.
+ (id)objectForKeyedSubscript:(id)key
{
unsigned int outCount;
if ([self instancesRespondToSelector:@selector(initWithCoder:)] && [key isKindOfClass:[NSCoder class]])
{
return [[self alloc] initWithCoder:key];
}
//todo: cache these results in an associated object
Method *theseMethods = class_copyMethodList(self, &outCount);
NSMutableIndexSet *methodArrayHits = [[NSMutableIndexSet alloc] init];
for (unsigned int i = 0; i < outCount; i++) {
NSString *initName = NSStringFromSelector(method_getName(theseMethods[i]));
if ([initName isEqualToString:@"initWithCoder:"])
{
continue;
}
if ([[NSString reasonableTypeEncodingForMethod:theseMethods[i]] isEqualToString:@"@@:@"] && [initName hasPrefix:@"initWith"])
{
[methodArrayHits addIndex:i];
}
}
if ([methodArrayHits count] == 1)
{
SEL sele = method_getName(theseMethods[[methodArrayHits firstIndex]]);
free(theseMethods);
return objc_msgSend(objc_msgSend([self alloc], sele, key), NSSelectorFromString(@"autorelease"));
}
return @"Foo!";
}
@nicklockwood
Copy link

How about:

+ (id)objectForKeyedSubscript:(id)key
{
    return [[self alloc] initWithKeyedSubscript:key];
}

- (id)initWithKeyedSubscript:(id)key
{
    unsigned int outCount;
    if ([self instancesRespondToSelector:@selector(initWithCoder:)] && [key isKindOfClass:[NSCoder class]])
    {
        return [self initWithCoder:key];
    }
    //todo: cache these results in an associated object
    Method *theseMethods = class_copyMethodList(self, &outCount);
    SEL initMethod = NULL;
    NSInteger count = 0;
    for (unsigned int i = 0; i < outCount; i++) {
        SEL method = method_getName(theseMethods[i]);
        NSString *initName = NSStringFromSelector(method);
        if ([initName isEqualToString:@"initWithCoder:"])
        {
            continue;
        }
        if ([[NSString reasonableTypeEncodingForMethod:theseMethods[i]] isEqualToString:@"@@:@"] && [initName hasPrefix:@"initWith"])
        {
            initMethod = method;
            count++;
        }
    }
    free(theseMethods);
    if (count == 1)
    {
        return objc_msgSend(objc_msgSend(self, initMethod, key); //you might still need to use objc_msgSend to call NSSelectorFromString(@"autorelease") on this value - depending on how ARC handles values returned from init when it doesn't know their retaincount
    }
    return @"Foo!";
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment