Skip to content

Instantly share code, notes, and snippets.

@groue
Last active December 17, 2015 12:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save groue/5610588 to your computer and use it in GitHub Desktop.
Save groue/5610588 to your computer and use it in GitHub Desktop.

Hello,

I'm working on a class that synthesizes its own property accessors when the user subclasses it, and declares properties @dynamic.

That class is part of the GRMustache library, and is documented in https://github.com/groue/GRMustache/blob/master/Guides/view_model.md

Today, the current implementation works, and is robust. The end user has a very simple API - he just has to declare dynamic properties in order to be granted with the features he needs. I'm quite happy of that.


However I had a big difficulty with "exotic" properties. You known, all those types that KVC wraps in NSValue: structs, unions, C arrays, etc.

For them I was totally unable to define IMP functions able to act as a getter and setter, and add synthesized methods in the user's class. To make it work, I had to rely on methodSignatureForSelector and forwardInvocation, and override respondsToSelector in order to remain on the light side of the force.

For instance, here are the straight-forward getter and setters for char properties:

static void managedPropertyCharSetter(GRMustacheContext *self, SEL _cmd, char value)
{
    NSString *key = managedPropertyNameForSelector([self class], _cmd);
    [self setValue:[NSNumber numberWithChar:value] forKey:key];
}

static char managedPropertyCharGetter(GRMustacheContext *self, SEL _cmd)
{
    NSString *key = managedPropertyNameForSelector([self class], _cmd);
    return [[self contextValueForKey:key protected:NULL] charValue];
}

I stumble on the way to define such functions that could take, or return, any kind of value (structs, unions, C arrays, etc).

I could never have the compiler compile something like the code below:

static void genericSetter(GRMustacheContext *self, SEL _cmd, /*any type*/ value);
static /*any type*/ genericGetter(GRMustacheContext *self, SEL _cmd);

Why do I ask this question, if the current code is already working?

For two reasons. A psychological one, and a good one.

First, I don't like the ObjC runtime to have dark corners for me. If it's impossible to synthesize struct/union/etc properties, I wish I knew why.

Second, not being able to synthesize all properties requires to add much picky code around, in order just to pretend bloody methods exist when they don't. Responding to unkown selectors, supporting Key-Value Coding, etc. just adds bloated code begging for bugs.


So. Do you have any hint to help me out actually synthesizing methods for those exotic types, and stop relying on forwardInvocation?

@yvbeek
Copy link

yvbeek commented Aug 13, 2013

I think you're looking for the equivalent of C++ templates in Objective-C. Unfortunately there is none. Your option would be to write it in a .mm file, but I'm not sure what that would mean for the compatibility of your library.

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