This year in WWDC, Apple introduced Objective-C ‘lightweight’ generics for XCode7. This builds upon the improvements to Objective-C to document the code and improve the interoperability with Swift. I wrote previously about nullability annotations and I continue to be delighted by these changes to the language. Here’s what I think.
Let me say it before we begin, the syntax is simple so we will not see (indispensable) sites like this one. This addition to the language allows to specify the compile-time type of the objects contained in collections. It looks like this:
1 2 3 4 5 6 7
Note the brackets on the declaration of the NSArray property. It lets the compiler check the types of APIs accepting
id and it will generate warnings by comparing the pointer types:
1 2 3 4 5 6 7 8 9 10 11 12
So now you can remove all the pesky comments to tell your colleagues and future self what these collections contain. Be aware that the generated code does not change, as we will see in the next sections.
All Foundation collections support generics: NSArray, NSMutableArray, NSSet, NSMutableSet, NSOrderedSet, NSMutableOrderedSet, NSDictionary, NSMutableDictionary, NSHashTable, NSMapTable.
The compiler will compare direct pointer types. This works correctly many times, but sometimes you want to still use the behaviour of
id but restricted to a base class. This is technically not safe, but is code you that you normally write. In this case you can use
kindof. Let’s add a subclass to our previous models. A handy square wheel:
1 2 3
Now that’s how you would use it sometimes, assuming that you will get the subclass:
1 2 3 4 5 6 7 8
In this case you can annotate the types with the
kindof keyword, to let the compiler know that you want to freely assume that subclasses of the specified type are also valid:
1 2 3
In your own code
You can also annotate APIs in your code. Let’s see an example:
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
The annotations are only for the API, and then your implementations are normal code. Then using the annotated API the compiler will check the static types:
1 2 3 4 5 6 7 8 9 10 11
The language didn’t change, and I would argue this is good. Apple didn’t hack it just for this feature. So you can still crash at runtime if your code works around this.
Let’s try to break it. A crashy example:
1 2 3 4 5 6 7 8 9 10 11 12
Adopting generics for existing projects
As with nullability, adopting this language changes will be tedious. I think the best candidates for this are the lower level parts of your code, specially domain and model objects. This will have higher impact on your codebase with the least amount of effort.
Objective-C advances to slowly make way to Swift. Apple is going full-steam with Swift and this change is more in favour of that language than of Objective-C itself.
But as many of us need to work with ‘legacy’ Objective-C code, ‘lightweight generics’ is nevertheless a welcomed addition.
I will mention again this is not a full ’generics’ implementation for Objective-C, but rather annotations for the compiler to check your API usage, and intention. It also changes how Swift sees the Objective-C code and improves interoperability between the languages. A win-win situation.