Dustin Bachrach

mobile engineer / developer platform enthusiast / dog lover

AtSugar: Sugar for Your @

We just released a small Header-Only library called AtSugar. AtSugar provides a few macros for Objective-C that make writing things easier and more declarative. The intention is to continue expanding this to form a great collection of helper utilities.

All macros in AtSugar hook into the @ sign, so they feel like Objective-C extensions. This is just a compiler trick. It’s not hooking into the runtime or doing anything funky. Before using AtSugar, I suggest taking a look at the individual header files to see how they work.

Let’s take a tour of what AtSugar simplifies.

Weak references

We typically need weak references when we are going to capture references to use later inside a block (to break the retain cycle). Here’s how we would do that with AtSugar:

1
2
3
4
@weakSelf()
[self saveBlock:^{
    [weakSelf go]; // `weakSelf` will be captured weakly
}];

Sometimes we want to weakly capture something besides self:

1
2
3
4
5
6
id obj = /* an object */;

@weakify(obj)
[self saveBlock:^{
    [weak_obj go];
}];

Singletons

However much we like to bash on them, we still use(need) singletons. With the @singleton directive we can declare our singleton intent clearly:

1
2
3
4
5
@interface MyClass : NSObject

+ (instancetype)sharedInstance;

@end
1
2
3
4
5
@implementation MyClass

@singleton(sharedInstance)

@end

Note that AtSugar is only aiding in the implementation. AtSugar is all about making your implementations clearer without changing your interfaces. Consumers of your classes shouldn’t care, or even be aware, of your AtSugar use.

Associated Objects

Associated objects are a great feature of Objective-C that allow us to add properties to categories. But using associated objects is harder than just declaring a property. AtSugar adds an associated_object directive to simplify the process.

1
2
3
4
5
@interface UIImage (MyCategory)

@property (strong, nonatomic) NSString* myProperty;

@end
1
2
3
4
5
6
7
#import <objc/runtime.h>

@implementation UIImage (MyCategory)

@associated_object (myProperty, setMyProperty)

@end

When using associated_object you need to specify the getter and setter. Ideally you could just do:

1
@associated_object (myProperty)

But the C preprocessor does not allow case translation, so we can’t turn myProperty into setMyProperty.

If you need to change the memory management rules for the associated object you can use the various other flavors:

  • associated_object_assign
  • associated_object_copy
  • associated_object_with_association

Declarative Class Properties

In our codebase, lots of our classes have constant properties about them. For example, all of our different models have a specific identifier prefix. All movie IDs begin with mov, and all user IDs begin with usr. So our root model object declares a class method:

1
2
3
4
5
@interface RootModel : NSObject

+ (NSString*)prefix;

@end

Each model subclass then needs to implement this method and return its constant prefix string. To make this very declarative, AtSugar provides declare_class_property:

1
2
3
4
5
@implementation Movie

@declare_class_property (prefix, @"mov")

@end
1
2
3
4
5
@implementation User

@declare_class_property (prefix, @"usr")

@end

Contribute

We’d love to see contributions to AtSugar from the community. Please fork and send us a pull request.

An Annotated NSArray

At Airstrip, we have lots of code built up around handling JSON model responses. We have a generic transformation process that can take JSON and instantiate concrete model objects. One of the major difficulties, though, is handling array relationships. Imagine the following model:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@interface Person : Model
@property (strong) NSString* name;
@property (strong) Address* address;
@property (strong) NSArray* phoneNumbers;
@end

@interface Address : Model
@property (strong) NSString* number;
@property (strong) NSString* street;
@property (strong) NSString* zip;
@end

@interface TelephoneNumber : Model
@property (strong) NSString* name;
@property (strong) NSString* number;
@end

Our app would receive the following JSON for a call to a specific endpoint that we know describes a Person.

1
2
3
4
5
6
7
8
{
    "name": "Dustin",
    "address": { "number": 123, "street": "Main St", "zip": 99999 },
    "phoneNumbers": [
        { "name": "mobile", "number": "555-555-5555" },
        { "name": "home", "number": "555-555-5556" }
    ]
}

When we parse this JSON and try to produce a Person model, we can easily fill in the name property. The Objective-C property is declared to be an NSString, and the JSON data contains the string “Dustin”. So we can just set the person’s concrete name property to “Dustin”. We know that the address property aligns with the address JSON attribute, so we can construct an Address instance and create it with this JSON:

1
{ "number": 123, "street": "Main St", "zip": 99999 }

Just like we could set the Person’s name to “Dustin”, we can set this new Address object’s number to be “123”, its street to be “Main St”, and its zip to be “99999”.

Getting back to parsing the JSON for the Person, it’s tough when we evaluate the phoneNumbers property. What we want to happen is to construct two TelephoneNumber classes, create an array that points to them, and then assign that to the concrete phoneNumbers property. But our JSON transformation system looks at the phoneNumbers property and sees the type NSArray.

We need to tell the transformation system extra information about what belongs inside the NSArray. We need an annotated NSArray.

The unfortunate reality is that it’s just not possible (if it is possible, I would love to be wrong, so tweet me). I’ll describe a bunch of alternatives to try and solve this problem, and give you my suggestions.

The unfortunate IBOutletCollection

I’ll start off with a non-solution. You may be aware of the IBOutletCollection macro, which you can use to annotate a property:

1
@property (weak) IBOutletCollection(UILabel) NSArray* labels;

In Interface Builder you can then hook up multiple label outlets to the labels property.

If you were hoping that this could magically be added to our model and used by our transformation system:

1
@property (strong) IBOutletCollection(TelephoneNumber) NSArray* phoneNumbers;

You would be sad to look up the definition of IBOutletCollection:

1
#define IBOutletCollection(ClassName)

Yeah, it gets removed and does us no good.

Protocols

Objective C Generics and JSONModel both take an interesting approach. They use protocols to annotate the contents of an NSArray rather than to describe behavior of the NSArray itself. Consider this example:

1
2
3
@interface Person : Model
@property (strong) NSArray<TelephoneNumber>* phoneNumbers;
@end

You then need to create a protocol with the same name as your class:

1
2
@protocol TelephoneNumber
@end

This absolutely works, and it’s a really clever workaround, but it’s very misleading. For this problem, where we are more concerned with annotation (like JSONModel), and less concerned with strict generics (like Objective C Generics), the syntax implies a lot more than we really want. We aren’t adding strict generics, but it looks like we are. You also have to create a protocol for each of your model classes, which is where the abstraction shows its leaks. I can’t entirely rule this option out because it does function properly. I’m just hesitant of what this might do for a large code base.

Getting your server involved

We could stop trying to annotate our Objective-C code, and annotate the JSON instead.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
    "_model": "Person",
    "name": "Dustin",
    "address": {
        "_model": "Address",
        "number": 123,
        "street": "Main St",
        "zip": 99999
    },
    "phoneNumbers": [
        {
            "_model": "TelephoneNumber",
            "name": "mobile",
            "number": "555-555-5555"
        },
        {
            "_model": "TelephoneNumber",
            "name": "home",
            "number": "555-555-5556"
        }
    ]
}

By pushing the burden to the server, we’ve now worked around Objective-C’s limitation and tightly coupled the server with the client’s class names. If your Android and iOS clients both use the same JSON endpoints, then now you have to ignore the _model field in Android, converge your Android and iOS class names, or add another JSON field: _modelAndroid.

If you rev your client, you may need to rev your server. Can your new server communicate with old clients? To be fair, there’s already tight coupling between server JSON and client concrete models. Maybe this method is not concerning to you. Maybe it’s a real issue.

Typed NSArrays

I went exploring down this path a bit. Basically:

1
2
3
4
5
6
@interface TelephoneNumbersArray : NSArray
@end

@interface Person : Model
@property (strong) TelephoneNumbersArray* phoneNumbers;
@end

This looks somewhat appealing. Just subclass NSArray and create your own typed array class. Sure, now every model class needs to create its own array, but even more concerning is how difficult subclassing NSArray is. It does not do what you think it does. Subclassed NSArrays do not provide the same implementation as [NSArray array]. You have to go implement your own array storage and conform to the NSArray interface. This is something I didn’t want to mess around with at the time, and my investigations ended there. Perhaps you can make this work. If you have, get in touch.

The oh-god-no option

I showed this to my boss, and he said he wanted to throw up. It’s truly terrible, and don’t use it, but I like the hack.

1
@property (getter = TelephoneNumber) NSArray* phoneNumbers;

Objective-C limits exactly what can be associated with a property. This guide describes it in detail, but a property has a name and a set of attributes (readonly/readwrite, atomicity, memory management, raw type, and getter/setters). Most of those are unusable booleans or enums, but getter/setter are strings. Rather than using the getter/setter for its normal use, we can stuff annotations in there.

At runtime we can inspect them via property_getAttributes() and then treat the getter as the NSArray’s annotated type rather than a getter.

I repeat, don’t do this.

Source rewriting

ObjectiveCAnnotate is a code generation tool that lets you add source-level annotations to your code that will be translated pre-compile-time.

For example:

1
2
//@properties (assign)
NSString *aVariable;

Will be transformed into:

1
@property (assign) NSString *aVariable;

ObjectiveCAnnotate doesn’t have built-in support for what we want, annotated NSArrays, but you could easily add support for it with their custom annotations.

I wasn’t huge on having to run a pre-compilation step in our build just to get this feature. And adding something like this certainly increases the complexity of your code, making a new-hire’s life more complicated.

Implicit property names

This is actually a reasonable solution, which requires no special annotation. Just name your properties as the plural name of a class. The transformation system can get the property name, singularize it, optionally prepend a namespace prefix, and there’s your annotated NSArray’s type.

In our example where the model class was named TelephoneNumber, we could change from:

1
@property (strong) NSArray* phoneNumbers;

to

1
@property (strong) NSArray* telephoneNumbers;

We could have instead changed our model class to be named PhoneNumber to match the property.

For most code you might not even need to rename. You likely are already naming your properties the same as your classes.

This is not a perfect solution. We are forming a tight coupling between our server and client because the server property names need to match the concrete class names.

It’s also reasonable to have a situation where you have to have different names:

1
2
3
4
@interface NationalOfficial : Model
@property (strong) NSArray* privateTelephoneNumbers;
@property (strong) NSArray* secureTelephoneNumbers;
@end

Here our NationalOfficial will have an array of private phone numbers and a separate array of secure phone numbers. If we require the property name to be the same as the class name, they can’t both point to TelephoneNumber, so we would only be able to have one telephone number array.

Explicit property transformer

Finally, we can give up our lofty goal of implicitly deducing this information and rely exclusively on explicitly listing property types.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@interface Model
- (NSDictionary*)transformableProperties;
@end

@interface PropertyType
+ (instancetype)typeOf:(Class)class;
+ (instancetype)arrayTypeOf:(Class)class;
+ (instancetype)integerType;
// ... all other primitive type constructors
@end

@implementation Person

- (NSDictionary*)transformableProperties
{
    return @{ "name": [PropertyType typeOf:[NSString class]],
              "address": [PropertyType typeOf:[Address class]],
              "phoneNumbers": [PropertyType arrayTypeOf:[TelephoneNumber class] };
}

@end

Each model object needs to override the -transformableProperties method and return a dictionary of property names to types. The PropertyType would be a class which can represent primitive types, class types, and annotated collection types.

The obvious downside is that we are having to repeat ourselves in our interface declaration and implementation. But we do get very explicit behavior that can be read by everyone of your developers (new or old), and it makes sense.

My preference

My personal view on this is to write as little code as possible. That’s why I set out on this whole process. Our current solution was the explicit property transformer, and I thought it was verbose, redundant, and difficult to maintain.

I think the right balance is in a mix of implicit and explicit. For most scenarios the implicit property names method works great. Once you understand it, it’s clean and beautiful. And if you ever need to support situations where your property names cannot match, use -transformableProperties. Any property names returned from there are used as specified and all others will be inferred.

Thanks for reading, and I hope this recap gives you enough information to make an informed decision. Please feel free to get in touch, especially if you have a solution I’m missing.

Sequence Unpacking in Objective-C

I like to look at other programming languages for inspiration. Most of us work in a single language on a daily basis. We start aligning our thought process to that language. We settle into certain tropes and styles based on the technical limitations of our language. Exploring other languages can introduce us to new concepts— like the simple conveniences in Ruby’s syntactic sugars, or the complex metaprogramming available in C++’s templates. In this post, we’ll take a look at one of Python’s features known as sequence unpacking.

Sequence unpacking

Python has this little beauty of code to swap variables a and b:

1
a,b = b,a

This is Python’s sequence unpacking. It’s obvious, concise, and extensible. Sequence unpacking goes by several names in other languages— ‘destructuring bind’ in Lisp or ‘parallel assingment’ in Ruby. We’re going to dive deeper into this feature with an Objective-C hat on. There are three typical uses for sequence unpacking:

  • Easy swapping is simple, elegant, and rids us of a temporary variable cluttering up things. Here’s swap without sequence unpacking:
1
2
3
4
5
int a = 5;
int b = 6;
int temp = a;
a = b;
b = temp;
  • Multiple return values ease the calee, so it can return distinct values without having to generate a new type or pass things by reference through extra parameters. Consider how you delete files:
1
2
NSError* error;
BOOL success = [[NSFileManager defaultManager] removeItemAtPath:path error:&error];

The remove method communicates two things— whether the file was removed, and detailed error information. With sequence unpacking you could do something similar:

1
2
3
BOOL success;
NSError* error;
(success, error) = [[NSFileManager defaultManager] removeItemAtPath:path];
  • Parsing out complex types eases the caller, so it can work directly on the needed data. Imagine you want to find the area of a UIView. You have to grab the bound’s size and then query for its width and height:
1
2
3
4
CGSize size = view.bounds.size;
CGFloat width = size.width;
CGFloat height = size.height;
CGFloat area = width * height;

With sequence unpacking you could move to a more concise version:

1
2
3
CGFloat width, height;
(width, height) = view.bounds.size;
CGFloat area = width * height;

The problem sequence unpacking solves is not huge. We make due in all three of these use cases with Objective-C. What sequence unpacking does is let us express our true intent succintly.

We all realize that when swapping two variables, we need to copy one value temporarily. Does that mean we need to explicitly write that? We know that you can simulate multiple return values with out parameters. But should we be forced to hide our intent through inderection? When we recieve a composite type, sure we can store it away and separately access its members. But why can’t we just directly recieve what we want in the format we want?

Let’s explore adding sequence unpacking to Objective-C. The source code to this blog post is available on GitHub under the MIT License.

Implementation

I’ll first declare the ideal syntax for sequence unpacking in Objective-C:

1
2
int x, y;
(x, y) = GetPoint();

Fat chance of that. Here’s the best we can do:

1
2
int x, y;
unpack (_(x, y) from GetPoint());

This syntax makes it look like we’ve introduced two new keywords— unpack and from. In reality from is just #defined from ,, so we’re left with:

1
unpack(_(x,y), GetPoint());

unpack is a function that takes something to pack up and somewhere to unpack it.

1
2
3
4
void unpack(id<PAKSeqUnpacker> unpacker, id<PAKSeqPacker> packer)
{
    [unpacker unpack:[packer pack]];
}

Two protocols define what’s required to make something packable or unpackable.

1
2
3
4
5
6
7
8
9
10
11
@protocol PAKSeqPacker <NSObject>

- (NSEnumerator*)pack;

@end

@protocol PAKSeqUnpacker <NSObject>

- (void)unpack:(NSEnumerator*)enumerator;

@end

If you want your class to be packable, then implement pack and return an enumerator. To allow unpacking, just implement unpack:, and you’ll recieve the enumerator that the packer created.

With these definitions, we have a flexible sequence unpacking system. The protocols let us easily support both packing and unpacking to/from arbitrary classes. With enumerators, classes can pack into any number of slots. Finally, the unpacker can unpack a different number of slots than the packer packed. For example, unpack (_(x,y) from Get3DPoint()) would only unpack the x and y coordinates of a three dimensional point and ignore the z coordinate.

Passthrough Tuples

You probably are wondering what this _(...) thing is. _ is a macro for easily creating a Tuple. What’s a Tuple? It’s a fixed and ordered list of elements. It’s a lightweight array. Having the _ macro for a Tuple makes it nice for packing up objects without having to create a custom class to contain them since Tuple implements the PAKSeqPacker protocol.

1
unpack (/* to some place */ from _(@1, @2));

Here, we’ve packed up 1 and 2 easily by placing them into a Tuple, and letting the Tuple take care of packing them.

It’s more interesting when we want to easily unpack values:

1
2
int x, y;
unpack (_(x, y) from /* some where */);

When the _ macro Tuple is on the left of the from, it acts as a simple container for unpacking variables. In the exmaple above, we want to unpack a value into the x variable. The Tuple needs to store a pointer to x. Passthrough Tuples store pointers to their contained objects. This allows them to read the contained variables’ values if the Passthrough Tuple will be packed, or write to the variables if the Passthrough Tuple will be unpacked.

So not only is _ acting as a shorthand for creating Passthrough Tuples, it’s also taking its parameters by reference instead of by value. It does this like so:

1
#define _(a, b) [PAKPassthroughTuple tupleWithA:(__strong id* )&a B:(__strong id* )&b]

Variadic Tuples

The definition of _ above is limited to only two parameters. Ideally, PassthroughTuple should take any number of parameters. The solution for this is not pretty.

1
2
3
4
5
6
#define PT_1(a) [PAKPassthroughTuple tupleWithValues:(__strong id* )&a, nil]
#define PT_2(a, b) [PAKPassthroughTuple tupleWithValues:(__strong id* )&a, (__strong id* )&b, nil]
// ... and so on to PT_10

#define GET_PT_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, NAME, ...) NAME
#define _(...) GET_PT_MACRO(__VA_ARGS__, PT_10, PT_9, PT_8, PT_7, PT_6, PT_5, PT_4, PT_3, PT_2, PT_1)(__VA_ARGS__)

We create a macro for creating a PassthroughTuple with one argument and call it PT_1. We make another one for two arguments and call it PT_2. We do this all the way up to PT_10.

Given these 10 macros, we then need a way to define an _ macro which can, based on the number of arguments, call the appropriate PT macro. We can do this by using this excellent trick.

Foundation support

Many Foundation classes can trivially be extended to support sequence unpacking.

  • NSEnumerator
  • NSArray
  • NSOrderedSet
  • NSDictionary

For example, here’s how we make NSArray packable:

1
2
3
4
5
6
@implementation NSArray (OCPAK)
- (NSEnumerator*)pack
{
    return [self objectEnumerator];
}
@end

With Foundation support, we can now do:

1
2
3
id a, b, c, k1, k2;
unpack (_(a, b, c) from @[@1, @2, @3]);
unpack (_(k1, k2) from @{@"a key" : @"value1", @"another key" : @"value2"}); // note: dictionary order is not guranteed

Packing structs

This sequence unpacking implementation only supports objects. It can’t pack primitives like structs. This is unfortunate since one of the examples I gave was to unpack a CGSize.

The only way to do this is to wrap the struct in an NSValue, and make the values you unpack into id (unpacked as NSNumbers).

1
2
3
CGSize size = CGSizeMake(20, 30);
id width, height;
unpack (_(width, height) from [NSValue valueWithCGSize:size]);

This requires us to add packing support to NSValue:

1
2
3
4
5
6
7
8
9
10
11
@implementation NSValue (OCPAK)
- (NSEnumerator*)pack
{
    if (strcmp(self.objCType, @encode(CGSize)) == 0)
    {
        CGSize size = self.CGSizeValue;
        return [@[@(size.width), @(size.height)] objectEnumerator];
    }
    return nil;
}
@end

Even cleaner in C++

Turning an eye towards another language, C++, it should be entirely possible to duplicate this work in C++. What could be even more interesting is to take advantage of C++’s operator overloading. In C++, classes can define implementations for operators like +, , etc. With that tool, I think you can make sequence unpacking as simple as:

1
_(x, y) << GetPoint();

If you are comfortable giving up the = operator to sequence unpacking, then you could even do:

1
_(x, y) = GetPoint();

That’s pretty amazing.

Final thoughts

Sequence unpacking is a convenient feature in other languages, and I wanted to see how we could bring that to Objective-C in the most concise way possible. The solution is flexible and functional, but has its limits. To make it look integrated into the language, I defined from to be a ,, which isn’t ideal. This solution also struggles with primitives, having to wrap them in NSValues. However, it’s really interesting to see how these sorts of features can be brought to an existing language. I hope you enjoyed this exercise, and feel free to get in touch if you have any thoughts.

OCUDL in Depth

Note: I have updated OCUDL to not rely on method swizzling. Please see the OCUDL World Ready section for more details.

Your UI designer is throwing hex values at you. “Update that button’s foreground color to #EEE000.” Or “that background should be #A23111 not #B23111.” This happens repeatedly. So now, everytime, you get to wrestle that hex value into:

+ (UIColor *)colorWithRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha;

We’re going from this concise, readable, and universally agreed upon syntax, #FFF123, and turning it into:

1
2
3
4
UIColor *myColor = [UIColor colorWithRed:255.0f
                                    blue:(241.0f / 2555.0f)
                                   green:(35.0f / 255.0f)
                                   alpha:1.0f];

Unfortunately, there’s no great way to clean this up. There are macros, which accept a hex value and spit out the above code. You could even go as far as extending UIColor via a category, adding a colorWithHex: helper.

If only our language let us express something like:

1
UIColor *myColor = #FFF123;

There is some precedence of this throughout Objective-C. For instance, you can make an NSString from @"abc", or an NSNumber from @12, or even an NSArray from @[@1, @2, @3]. There’s even precedence in other languages like C++, which have user defined literals today.

These Objective-C literals are baked into the compiler. If we want to get a UIColor literal like these ones, we’d need to go to the compiler writers. Let’s try to avoid that and build a user defined literal system for Objective-C based entirely on what exists today— no change to the language and no change to the runtime.

This blog post explores the in-depth process of creating this system. To get a quick overview and see it in action, take a look at Introducing OCUDL. This project’s source is available on GitHub.

OCUDL

OCUDL, Objective-C User Defined Literals, will allow us to create arbitrary literals associated with any class.

Imagine a class that will measure bytes and indicate whether it’s too large for the system memory:

1
2
3
4
5
6
@interface MyBytes : NSObject {
    NSInteger bytes;
}

- (BOOL)isTooLarge;
@end

When we are working with MyBytes object, it would be convenient to refer to them like:

1
[55b isTooLarge] // 55 bytes

We need to tell our system that any time it sees a literal that ends with a b, it should actually create a MyBytes object.

Literal constructors

A user defined literal can either be a prefix (the # in #FFF123) or a suffix (the b in 55b). When our system recognizes a prefix or suffix, it will instantiate an associated class and pass along the literal (FFF123 or 55, respectively). The class should conform to the OCUDLClass protocol, so it can be instantiated with the literal:

1
2
3
4
5
6
7
@protocol OCUDLClass <NSObject>

@optional
- (id)initWithLiteral:(NSString*)literal prefix:(NSString*)prefix;
- (id)initWithLiteral:(NSString*)literal suffix:(NSString*)suffix;

@end

We can update the MyBytes class to conform to the OCUDLClass protocol:

1
@interface MyBytes : NSObject <OCUDLClass> {

And implement the -initWithLiteral:suffix: constructor:

1
2
3
4
5
6
7
8
9
10
11
@implementation MyBytes

- (id)initWithLiteral:(NSString*)literal suffix:(NSString*)suffix
{
    if (self = [super init]) {
        bytes = [literal integerValue];
    }
    return self;
}

@end

OCUDLManager

We need a manager object that will handle all of these user defined literal registrations.

1
2
3
4
5
6
7
8
9
10
11
@interface OCUDLManager : NSObject

@property (strong, nonatomic) NSMutableDictionary *prefixMapping;
@property (strong, nonatomic) NSMutableDictionary *suffixMapping;

+ (instancetype)defaultManager;

- (void)registerPrefix:(NSString*)prefix forClass:(Class<OCUDLClass>)class;
- (void)registerSuffix:(NSString*)suffix forClass:(Class<OCUDLClass>)class;

@end

The implementation of OCUDLManager is fairly simple. We make it a singleton, which can be accessed via +defaultManager.

1
2
3
4
5
6
7
8
9
10
11
12
13
@implementation OCUDLManager

static dispatch_once_t s_pred;
static OCUDLManager *s_manager = nil;

+ (instancetype)defaultManager
{
    dispatch_once(&s_pred, ^{
        s_manager = [[OCUDLManager alloc] init];
    });

    return s_manager;
}

On initialization, we set up the prefix and suffix mapping dictionaries.

1
2
3
4
5
6
7
8
9
- (id)init
{
    if (self = [super init])
    {
        self.prefixMapping = [[NSMutableDictionary alloc] init];
        self.suffixMapping = [[NSMutableDictionary alloc] init];
    }
    return self;
}

Both registerPrefix:forClass and registerSuffix:forClass map the prefix and class into the manager’s dictionaries.

1
2
3
4
5
6
7
8
9
10
11
- (void)registerPrefix:(NSString*)prefix forClass:(Class<OCUDLClass>)class
{
    self.prefixMapping[prefix] = class;
}

- (void)registerSuffix:(NSString*)suffix forClass:(Class<OCUDLClass>)class
{
    self.suffixMapping[suffix] = class;
}

@end

Registering MyBytes

The MyBytes class can register with the manager to correlate the b suffix with itself.

1
2
3
4
5
6
7
8
9
10
@implementation MyBytes

static NSString* const ByteLiteral = @"b";

+ (void)load
{
    [[OCUDLManager defaultManager] registerSuffix:ByteLiteral forClass:[MyBytes class]];
}

@end

The +load method is called only once when a class or category is loaded into the runtime. This is the perfect time to register the MyBytes user defined literal.

A caveat

So far, so good. We have a lot of the infrastructure for user defined literals. We have an example class, MyBytes, which registers a suffix and a class with our manager. The manager stores a dictionary of all prefix/suffix and class pairs. But we still need a way to go from seeing 55b and calling [[MyBytes alloc] initWithLiteral:suffix:]. How do we do that?

Well, we can’t. There’s no way to hook into what the compiler does when it parses 55b.

We need to adjust our literal syntax just slightly. How about @"55b"? Unlike 55b, this will at least compile because it’s just a string. Now we can just hook into the initialization method that the compiler calls when it sees @"55b".

Oh, wait. NSString literals are special.

You may have noticed that you don’t need to retain and release NSString literals like you do other objects (although it’s still a good idea to do so just out of habit). In fact, you can release them as many times as you want and it won’t do anything. This is because NSString literals aren’t dynamically allocated like most Objective-C objects. Instead, they’re allocated at compile time as a part of your binary, and live for the lifetime of your process.

So NSString literals are not going to suffice. They are compiled into the binary and don’t behave like normal Objective-C classes.

Don’t fret. Along with all of those cool literals for NSArray and NSNumber that Apple added recently, they also added boxed C String literals.

1
@("55b")

It looks very similar to NSString literals, but it behaves differently. Boxed C String literals are dynamically allocated. This gives us a chance to hook into the allocation flow and work our magic.

But to do that magic, we need to dive into the dark waters of method swizzling.

Swizzling up a literal

1
2
3
4
5
6
7
8
9
#import <objc/runtime.h>
#import <objc/message.h>

void Swizzle(Class c, SEL orig, SEL new)
{
    Method origMethod = class_getClassMethod(c, orig);
    Method newMethod = class_getClassMethod(c, new);
    method_exchangeImplementations(origMethod, newMethod);
}

Take a look at that for a second. You may not have seen code like this before. These are actually C functions that form the underpinnings of the Objective-C runtime. Our Swizzle() function takes a Class and two selectors to class methods. We can use this wildly amazing method_exchangeImplementations() function to swap the implementations of these two methods.

So if I have a class with two class methods +foo and +bar, which I’ve swizzled. When I call +foo, the implementation of +bar is invoked. When I call +bar, the implementation of +foo is invoked.

Why the hell would you want to do that?

Imagine we want to override an existing class’ function with custom behavior. But in some cases, we don’t want custom behavior; we actually want to call back into the original behavior. Exchanging the method implementations allows us to swap in our custom behavior and then fall back onto the original one if we want to.

When a boxed C String literal gets evaluated at runtime it calls [NSString stringWithUTF8String:]. We are going to swizzle our own implementation of that in its place. We’ll check if the string that’s being created has one of our registered prefixes or suffixes. If it does, we’ll instantiate the associated class instead. If the string being created does not match our prefixes or suffixes, then we will just fall back on the original NSString implementation of stringWithUTF8String:.

We add a category method to NSString that will implement our custom behavior.

1
2
3
4
5
@interface NSString (OCUDL)

+ (instancetype)ocudlStringWithUTF8String:(const char *)nullTerminatedCString;

@end

We then swizzle it when our category gets loaded into the runtime.

1
2
3
4
5
6
7
8
@implementation NSString (OCUDL)

+ (void)load
{
    Swizzle([NSString class],
            @selector(stringWithUTF8String:),
            @selector(ocudlStringWithUTF8String:));
}

And we implement ocudlStringWithUTF8String:.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
+ (id)ocudlStringWithUTF8String:(const char *)nullTerminatedCString
{

    // Call through original stringWithUTF8String: implementation
    NSString *str = [NSString ocudlStringWithUTF8String:nullTerminatedCString];

    NSMutableDictionary *prefixMapping = [OCUDLManager defaultManager].prefixMapping;

    for (NSString *prefix in prefixMapping) {
        if ([str hasPrefix:prefix]) {
            str = [str substringFromIndex:[prefix length]];

            Class class = prefixMapping[prefix];
            id<OCUDLClass> literalClass = [class alloc];
            return (id)[literalClass initWithLiteral:str prefix:prefix];
        }
    }

    /* Handle suffixes ... */

    return str;
}

We first call through to the original stringWithUTF8String: implementation. We then search through each prefix we have registered and see if the current string has that prefix. If it does, then we instantiate the class associated with it. We would then do the same for suffixes.

Macro cleanup

At this point we have a working implementation of user defined literals. But to use them you have to do:

1
[(id)@("55b") isTooLarge];

Since a boxed C String will return an NSString, the compiler is going to complain about not finding an isTooLarge method. We can cast the result of our literal to id, to let the compiler know we are aware of our hacky approach.

@("55b") also looks more like a string than a literal. We can clean all of this up and make it look more like a literal with a macro.

1
#define $(literal) ( (id) ( @(#literal) ) )

In the macro definition, we can use the # operator to stringify the argument. For example:

1
2
3
#define STRING_IT(arg) #arg

STRING_IT(abc); // -> "abc", cool huh?

With our $ macro defined, we can simply use one of our user defined literals:

1
[$(55b) isTooLarge];

The power of blocks

Our implementation, so far, works best for associating a prefix or suffix with a class you own. We could make a user defined literal for UIColor, but we need to start adding categories on UIColor to implement -initWithLiteral:prefix:.

Let’s simplify this with blocks. We’ll add block versions of our registration methods on OCUDLManager.

1
2
- (void)registerPrefix:(NSString*)prefix forBlock:(OCUDLBlock)block;
- (void)registerSuffix:(NSString*)suffix forBlock:(OCUDLBlock)block;

OCUDLBlock is just a typedef for our block:

1
2
3
4
5
6
/**
 * Invoked when a user defined literal should be created.
 * The first parameter is the literal.
 * The second parameter is the prefix/suffix.
 */
typedef id (^OCUDLBlock)(NSString*, NSString*);

We can implement them identically to the Class version and just save the block into the prefix/suffix dictionary.

1
2
3
4
5
6
7
8
9
- (void)registerPrefix:(NSString*)prefix forBlock:(OCUDLBlock)block
{
    self.prefixMapping[prefix] = block;
}

- (void)registerSuffix:(NSString*)suffix forBlock:(OCUDLBlock)block
{
    self.suffixMapping[suffix] = block;
}

To finish support for blocks, we need to update ocudlStringWithUTF8String:.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
for (NSString *prefix in prefixMapping) {
    if ([str hasPrefix:prefix]) {
        str = [str substringFromIndex:[prefix length]];

        id mapping = prefixMapping[prefix];

        if (class_isMetaClass(object_getClass(mapping))) {
            Class class = mapping;
            id<OCUDLClass> literalClass = [class alloc];
            return (id)[literalClass initWithLiteral:str prefix:prefix];
        }
        else if ([mapping isKindOfClass:NSClassFromString(@"NSBlock")]) {
            OCUDLBlock block = mapping;
            return block(str, prefix);
        }
    }
}

When we find a matching prefix, we extract the value out of the prefix map for that prefix. It can either be a Class or a block. Testing whether an object is a block or a Class is interesting. To test for a class you use:

1
class_isMetaClass(object_getClass(mapping))

The type Class, itself can respond to object_getClass(), and returns a special type of class called a Meta Class. The Objective-C runtime has a class_isMetaClass() function specifically for testing if a value is a meta class.

To test if an object is a block we can use NSObject’s isKindOfClass:, but to get a Class for a block, we need to use NSClassFromString(@"NSBlock").

Once we know, the registration was for a block, we can invoke the block directly.

We now fully support block based user defined literals. Let’s try one out. We’ll create a .xib suffix, which will create an UINib for a literal.

1
2
3
4
[[OCUDLManager defaultManager] registerSuffix:@".xib"
                                     forBlock:^id(NSString *literal, NSString *prefix) {
     return [UINib nibWithNibName:literal bundle:nil];
 }];

Multiple suffixes

Let’s expand MyBytes to support a few more suffixes:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
static NSString* const ByteLiteral = @"b";
static NSString* const KiloByteLiteral = @"kb";
static NSString* const MegaByteLiteral = @"mb";

+ (void)load
{
    [[OCUDLManager defaultManager] registerSuffix:ByteLiteral forClass:[MyBytes class]];
    [[OCUDLManager defaultManager] registerSuffix:KiloByteLiteral forClass:[MyBytes class]];
    [[OCUDLManager defaultManager] registerSuffix:MegaByteLiteral forClass:[MyBytes class]];
}

- (id)initWithLiteral:(NSString*)literal suffix:(NSString*)suffix
{
    if (self = [super init]) {
        NSInteger value = [literal integerValue];

        NSDictionary* byteMultipliers = @{ ByteLiteral : @1,
                                           KiloByteLiteral : @1000,
                                           MegaByteLiteral : @1000000 };

        NSNumber* multiplier = byteMultipliers[suffix];
        if (multiplier)
        {
            bytes = value * [multiplier integerValue];
        }
        else
        {
            bytes = 0;
        }
    }
    return self;
}

I now should be able to create kilobyte and megabyte literals:

1
2
3
[$(4kb) isTooLarge];
[$(6kb) isTooLarge];
[$(3mb) isTooLarge];

Unfortunately, we have a minor issue in our suffix searching. We find the first suffix that matches, and in this case the b suffix is found before the kb suffix is found. We can fix up our ocudlStringWithUTF8String: method easily by searching through longer suffixes before shorter ones:

1
2
3
4
5
6
7
8
NSMutableDictionary *suffixMapping = [OCUDLManager defaultManager].suffixMapping;
NSArray *sortedSuffixMappingKeys = [[suffixMapping allKeys] sortedArrayUsingComparator:
    ^NSComparisonResult(id obj1, id obj2) {
    return[@([obj2 length]) compare:@([obj1 length])];
}];

for (NSString *suffix in sortedSuffixMappingKeys) {
    // ...

It’s also important to note that OCUDL can only have one class or block associated with a prefix/suffix. You cannot register a prefix/suffix more than once.

Unintended literals

Lots of code calls into stringWithUTF8String: not intending to use user defined literals at all. You can set a breakpoint in ocudlStringWithUTF8String: just to see how much framework and system code is going through there. If, by chance, the system is creating a string that happens to have a suffix you registered, then suddenly things will start to go crazy very quickly.

We need a way to easily know that the string passed into ocudlStringWithUTF8String: was intended to be a user defined literal.

Let’s prefix all user defined literal strings with a well known identifier, so our system can definitively tell if a string that was passed in is a user defined literal.

We’ll use a UUID as the identifier. We can create one easily in the Terminal by using the uuidgen command. We can then update the $ macro to include our well known UUID before the literal.

1
#define $(literal) ( (id) ( @("9AD499E3-61B8-43AC-83A1-4B322E67C9B3" #literal) ) )

This uses a nice C trick to concatenate string literals:

1
char* str = "xyz" "abc"; // str = "xyzabc"

We can then modify ocudlStringWithUTF8String: to check for our prefix.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
+ (id)ocudlStringWithUTF8String:(const char *)nullTerminatedCString
{

    // Call through original stringWithUTF8String: implementation
    NSString *str = [NSString ocudlStringWithUTF8String:nullTerminatedCString];

    NSString *ocudlUuid = @"9AD499E3-61B8-43AC-83A1-4B322E67C9B3";
    if ([str hasPrefix:ocudlUuid])
    {
        // Only treat as a user defined literal if has UUID as a prefix
        // ...
    }

    return str;
}

Back to UIColor

With our user defined literal system complete, we can now return to creating a literal for UIColor.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
[[OCUDLManager defaultManager] registerPrefix:@"#"
 forBlock:^id(NSString *literal, NSString *prefix) {
     unsigned int value = 0;
     if ([[NSScanner scannerWithString:literal] scanHexInt:&value])
     {
         if (literal.length == 6)
         {
             // 6 digit hex (#FFFFFF)
             return [UIColor colorWithRed:((float)((value & 0xFF0000) >> 16)) / 255.0
                                    green:((float)((value & 0x00FF00) >> 8)) / 255.0
                                     blue:((float)(value & 0x0000FF)) / 255.0
                                    alpha:1.0];
         }
         else if (literal.length == 3)
         {
             // 3 digit hex (#FFF)
             return [UIColor colorWithRed:((float)((value & 0xF00) >> 8)) / 15.0
                                    green:((float)((value & 0x0F0) >> 4)) / 15.0
                                     blue:((float)(value & 0x00F)) / 15.0
                                    alpha:1.0];
         }
     }
     else
     {
         // Color names (#black)
         if ([literal caseInsensitiveCompare:@"black"] == NSOrderedSame)
         {
             return [UIColor blackColor];
         }
         // Check for all the other UIColor default color names
         // ...
     }
     return nil;
}];

A different approach

If method swizzling makes you weary, we could avoid it and get a slightly more verbose user defined literal. Instead of creating our literal’s class when the boxed C string is created, we could hang a property off of an NSString category and do the literal evaluation there.

1
[@"55b".e isTooLarge];

Here, we’ve just created an NSString literal as usual and called through to an e property which evaluates the NSString as if it were a user defined literal and returns a MyBytes object.

This certainly avoids the runtime fudging, but at the price of readability.

Downsides

OCUDL is an experiment and has some downsides. I’m personally, hesitant to swizzle an often used method like stringWithUTF8String:. There may be a performance impact for doing so, or potential conflicts. I even ran into weird behavior where my unit test project did not swizzle the method correctly. I think the unit tests are bootstrapped differently, and the runtime swizzling did not take effect there. I ended up moving the swizzling from +load to initialization of the OCUDLManager to work around this issue.

There are a few usability issues too. When using these literals, the compiler is unaware of the types, so code completion won’t work. Also, since the compiler is unaware of what we’re doing, we can’t create a literal like $(http://apple.com), because the // are parsed as comments.

As long as you understand what’s going on under the hood, none of these downsides are too prohibitive.

OCUDL – World Ready

UPDATE: I originally created OCUDL as a fun experiment to see how close I could get to C++’s user-defined literals. I really liked the boxed C string approach and in the end couldn’t get that to a concise notation. So I wrapped it in a $ macro and that was that. A few people (@percysnoodle, @hypercrypt, and others) commented that since I was using a macro already, we could bypass boxed C strings and method swizzling. Instead we can just define:

1
#define $(literal) [[OCUDLManager defaultManager] objectForLiteralString:@"" #literal]

This directly instantiates an object for a literal string. It’s certainly less “cool”, but it’s functional, practical, and safe for production.

Although OCUDL started as an academic exploration, I think it’s best to switch implementations. The latest source on GitHub has been updated making OCUDL “world ready”. No more swizzling, no more runtime hacking.

Wrap up

OCUDL is a fun exercise in exploring the Objective-C runtime. It’s a testament to the dynamism of the language that we could even get this far. We got to explore some interesting parts of the Objective-C language, runtime, and even a few C tricks. I hope this look into creating OCUDL taught you a few new things. I certainly learned a lot. If you have any feedback or input, feel free to get in touch.

Introducing OCUDL

OCUDL is an experiment to bring user defined literals to Objective-C. A literal is a shorthand expression that creates a value of a certain type. For example, 25ul creates an unsigned long of 25, and @"hello" creates an NSString of hello. User defined literals bring this brevity and expressivity to our own types.

Literals are usually baked right in to the compiler. OCUDL, however, does not extend the compiler; it simply uses what already exists in the Objective-C runtime. You can learn more about OCUDL’s internals at OCUDL In Depth.

The OCUDL source is available on GitHub under the MIT License. Documentation is at CocoaDocs. Pull requests, bugs, and issues are welcome.

Example

OCUDL defines literals using prefixes or suffixes. Here, we’ve defined a UIColor literal that uses the # prefix.

1
2
// Creates a UIColor
myView.backgroundColor = $(#FE22AA);

The $ tells OCUDL to interpret this value as a user defined literal. If user defined literals were baked right into the language, you wouldn’t need the $ at all.

Explore the Useful Literals section for additional examples of literals for UIKit and Foundation types.

Experimental

OCUDL is an experiment, and might not be appropriate for your project. Please read OCUDL In Depth to understand what’s happening behind the scenes.

Using OCUDL

You can get OCUDL through CocoaPods. You can learn more about dependency management with CocoaPods, but we’ll cover the basics.

Install CocoaPods:

1
2
gem install cocoapods
pod setup

Create a Podfile, in your project directory. Add the following lines:

1
2
3
platform :ios

pod 'OCUDL'

Then install the Podfile:

1
pod install

CocoaPods will create a .xcworkspace for you if you haven’t already created one. You will need to open your code in XCode through the workspace file and not the .xcodeproj file from now on.

Now your project is all set to use OCUDL. Get started by importing the header:

1
#import <OCUDL/OCUDL.h>

To create a literal for your class, first implement the OCUDLClass protocol.

1
@interface YourClass : NSObject <OCUDLClass>

Then, register a literal prefix or suffix for your class.

1
2
3
4
5
6
@implementation YourClass
+ (void)load
{
    [[OCUDLManager defaultManager] registerSuffix:@"your-suffix" forClass:[YourClass class]];
}
@end

Finally, implement the literal initializer.

1
2
3
4
5
6
7
- (id)initWithLiteral:(NSString*)literal suffix:(NSString*)suffix
{
    if (self = [super init]) {
        // ...
    }
    return self;
}

Now you can use your literal anywhere in your project.

1
YourClass *foo = $(555your-suffix);

Blocks

Sometimes you might want to add literals for classes you didn’t author. Instead of using categories, just use OCUDL’s support for blocks.

1
2
3
[[OCUDLManager defaultManager] registerPrefix:@"#" forBlock:^id(NSString *literal, NSString *prefix) {
    // return a new instance of some class
}];

Useful literals

OCUDL comes with many useful built-in literals for UIKit and Foundation types.

1
2
3
4
5
#import <OCUDL/OCUDLBuiltins.h>

// ...

[OCUDLBuiltins use];

After you [OCUDLBuiltins use], you can take advantage of all the built-in literals anywhere in your code.

NSNull

1
NSNull *n = $(null);

NSURL

1
2
NSURL *url = $(http:www.apple.com);
NSURL *url2 = $(https:www.gmail.com);

NSUUID

1
NSUUID *uuid = $(68753A44-4D6F-1226-9C60-0050E4C00067uuid);

UIColor

1
2
3
UIColor *color = $(#FE22AA);
UIColor *color2 = $(#FFF);
UIColor *color3 = $(#yellow);

UIImage

1
UIImage *img = $(pic.img);

UINib

1
UINib *nib = $(MyNib.xib);

UIStoryboard

1
UIStoryboard *board = $(MyBoard.storyboard);