Improving upon dictionary bindings.

iOS and OSX expose many of their APIs as dictionaries.   This means that instead of having properties or methods to configure a particular object, the configuration takes place by creating dictionaries that use some special keys with their associated values.   These APIs are not well suited for exploration from the IDE or from our REPL.   The APIs typically look like this:

CFStringRef keys[] = {
CFTypeRef  bval[] = {

attr = CFDictionaryCreate (kCFAllocatorDefault,
        (const void **) &keys, (const void **) &bval,
        sizeof(keys) / sizeof(keys[0]), &kCFTypeDictionaryKeyCallBacks,

astr = CFAttributedStringCreate(kCFAllocatorDefault, CFSTR("FFFFFF"), attr);

To make the API more easy to discover through intellisense, and our assembly browser, we try to turn all of the Dictionary-based APIs into strongly typed classes that hide the dictionary, the names of the keys, and the types of the keys required.   The responsibility for getting the types right, to get the encoding working and to figure out which keys are valid or required in a dictionary are shifted from the programmer to the framework developers (in this case, MonoTouch and MonoMac developers).

What we typically do is we create a type that exposes all of the properties that might be supported by the dictionary, and we provide nullable version of them, for example, in the above case, Mono’s implementation lives in the CFStringAttributes class, and the properties that we expose are these:

public class CFStringAttributes ()
    public CTFont Font { get; set; }
    public CGColor ForegroundColor { get; set; }

Our users then instantiate configuration objects like this:

var attrs = new CFStringAttributes () {
    Font = listLineCTFont,
    ForegroundColor = UIColor.Black.CGColor
var astr = new NSAttributedString ("FFFFFF"), attrs);

When you create your CFStringAttribute and start a new-line to enter properties, MonoDevelop knows the possible property values that you can initialize in the constructor, avoiding an entire trip to the documentation to figure out what is the key that you should use, the value and its encoding. It is all kept on type-safe datatypes.

There is a second class of APIs, mostly in the Audio and Video APIs that exposes a whole set of properties behind fooGetProperty and fooSetProperty APIs. Those APIs tend to be weakly typed, and take both a key, and depending on the key, a pointer to some value. If you feed the wrong values to the program, your application could crash or corrupt its heap. In these cases we have also walked away from exposing the low-level GetProperty/SetProperty methods, and instead exposed strongly-typed C# properties.

This is an example from the AudioFile API:

        AudioFileGetProperty (

In the above case, we are probing for the maximum packet size for the file. The user has to find and pass the proper constant (kAudioFilePropertyPacketSizeUpperBound), the size of the object (this is a simple validation system to eliminate a certain class of memory corruption erors), the address of the variable that will get the result back, and then determine the proper type for the property (maxPacketSize).

What we have tried to do with MonoTouch/MonoMac is hide all of that complexity, and instead we expose strongly typed properties, in this case the equivalent code is:

var maxPacketSize = audioFile.PacketSizeUpperBound;

The property is available as well for intellisense, so it is a lot simpler to see what is going on behind the scenes, shows up on the debugger window, on the interactive shell and means that scripting languages can access it without having to resort to reading C API documentation.

This entry was posted in Uncategorized. Bookmark the permalink.

3 Responses to Improving upon dictionary bindings.

  1. One thing possibly worth noting is that the strongly-typed dictionary wrappers often provide interoperability support by accepting NSDictionary instances in the constructor and providing a Dictionary property to provide “raw” access to the underlying dictionary. Consider MonoTouch.CoreText.CTStringAttributes:

    A constructor is provided to wrap an existing NSDictionary:

    and a property is provided to access the wrapped NSDictionary:

    This makes it fairly trivial to construct a strongly-typed wrapper over an NSDictionary acquired from “elsewhere”, providing nice IDE support.

  2. alex says:

    Neat. Is this done by some sort of generator or is it hand-made every time?

    • So far they have all been hand-written. There is really no consistent pattern that emerges as it seems to have been a tendency, but not really one that got strictly standardized, so there are some slight differences across the various APIs.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s