0

I'm implementing a dynamic property getters/setters using resolveInstanceMethod::

ref https://stackoverflow.com/a/13646650/132087

+ (BOOL)resolveInstanceMethod:(SEL)aSEL {
    if ([NSStringFromSelector(aSEL) hasPrefix:@"set"]) {
        class_addMethod([self class], aSEL, (IMP)setPropertyIMP, "v@:@");
    } else {
        class_addMethod([self class], aSEL,(IMP)propertyIMP, "@@:");
    }
    return YES;
}

static id propertyIMP(id self, SEL _cmd) {
    return [[self properties] valueForKey:NSStringFromSelector(_cmd)];
}

static void setPropertyIMP(id self, SEL _cmd, id aValue) {

    id value = [aValue copy];
    NSMutableString *key = [NSStringFromSelector(_cmd) mutableCopy];

    // delete "set" and ":" and lowercase first letter
    [key deleteCharactersInRange:NSMakeRange(0, 3)];
    [key deleteCharactersInRange:NSMakeRange([key length] - 1, 1)];
    NSString *firstChar = [key substringToIndex:1];
    [key replaceCharactersInRange:NSMakeRange(0, 1) withString:[firstChar lowercaseString]];

    [[self properties] setValue:value forKey:key];
}

I want to be able to support non-object types (such as enums and integers) using this general pattern by "boxing" them inside NSNumbers. To do this, I need to determine what type will be passed into the setter.

Is this possible? I've stretched my knowledge of the Obj-C runtime as far as I can take it, but I can't seem to resolve a way to determine the type of value being passed into the setter.

Community
  • 1
  • 1
Erik Kerber
  • 5,646
  • 7
  • 38
  • 56
  • If the properties are still declared in your class's interface, it is possible to get the type encoding from the property itself (though if there is no property you're out of luck, as selectors contain no type information). You could then box & unbox the values with some target specific assembly, along with NSGetSizeAndAlignment. I can't honestly say it would be worth the effort in my opinion, however. – Richard J. Ross III Apr 03 '14 at 08:47
  • @RichardJ.RossIII I did end up going this route, though it was not my ideal situation. The actual concrete class had nothing declared, and I instead was sending it arbitrary messages. The messages come from protocols with properties, so I had to pass in the protocol and use protocol_getProperty() to get the type encoding. – Erik Kerber Apr 03 '14 at 16:48
  • You could have always iterated through the class's protocols, assuming you declared the protocol in the interface of course. – Richard J. Ross III Apr 03 '14 at 19:54
  • @RichardJ.RossIII I didn't :). – Erik Kerber Apr 03 '14 at 21:43

0 Answers0