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
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
If only our language let us express something like:
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.
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
When we are working with MyBytes object, it would be convenient to refer to them like:
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.
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
We can update the MyBytes class to conform to the OCUDLClass protocol:
And implement the
1 2 3 4 5 6 7 8 9 10 11
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
The implementation of OCUDLManager is fairly simple. We make it a singleton, which can be accessed via
1 2 3 4 5 6 7 8 9 10 11 12 13
On initialization, we set up the prefix and suffix mapping dictionaries.
1 2 3 4 5 6 7 8 9
registerSuffix:forClass map the prefix and class into the manager’s dictionaries.
1 2 3 4 5 6 7 8 9 10 11
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
+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.
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
We need to adjust our literal syntax just slightly. How about
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
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.
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
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
+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
We add a category method to NSString that will implement our custom behavior.
1 2 3 4 5
We then swizzle it when our category gets loaded into the runtime.
1 2 3 4 5 6 7 8
And we implement
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
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.
At this point we have a working implementation of user defined literals. But to use them you have to do:
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.
In the macro definition, we can use the
# operator to stringify the argument. For example:
1 2 3
$ macro defined, we can simply use one of our user defined literals:
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
Let’s simplify this with blocks. We’ll add block versions of our registration methods on OCUDLManager.
OCUDLBlock is just a typedef for our block:
1 2 3 4 5 6
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
To finish support for blocks, we need to update
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
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:
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
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
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
I now should be able to create kilobyte and megabyte literals:
1 2 3
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
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.
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.
This uses a nice C trick to concatenate string literals:
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
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
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.
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.
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.
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:
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.
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.