I am the first to be surprised to find a post about good old Objective-C in this blog. This Sexy Software Engineer has not written any Objective-C code in almost a year! This Sexy Software Engineer, though, still enjoys using the Royal We. Some things ain’t changin’
A little bit of ancient history
Those, like me, old enough to be around in the “good old days”, before ARC, when memory had to be manually managed, will remember how a proper constructor (sorry, initializer) in a proper Objective-C class was supposed to return id
@interface SexySoftwareEngineer - (id) initWithName: (NSString*) name surname: (NSString *) surname; @end
id meant “Yo! Compiler! This is untyped! Have fun with it!” Or something similar. You get the point.
But then ARC came in with all its modern memory management, and all its fancy annotations, and suddenly, the right thing to do was to type return types in initialisers as instancetype
@interface SexySoftwareEngineer - (instancetype) initWithName: (NSString*) name surname: (NSString *) surname; @end
A little bit of contemporary history
Here we are now, one year into the Swift age. Lots of things have changed, and most of us do not consider the fully dynamic nature of Objective-C a selling point anymore. We might still miss it sometimes, but we like the warm and fuzzy feeling of relying on the compiler, and let it catch potential problems for us.
But, and this is a big but, we still need to rely on Objective-C libraries and frameworks daily. And those are not trivial libraries, those are the actual SDK frameworks (AppKit, UIKit and Foundation), which are still Objective-C
Apple is doing a great job in making the interoperability as smooth as possible. Please, watch the WWDC Session Swift and Objective-C interoperability right now, and you will get a great walkthrough everything that has been done in order to turn Swift code that uses Objective-C code into something safe. Let’s just say that now you can do something like this:
@interface SexySoftwareEngineer - (Nullable instancetype) initWithName: (nonnull NSString*) name surname: (nonnull NSString *) surname; @end
Back to the point: what’s with id?
By adding some extra metadata to the Objective-C code, like nullability and “kindof” annotations, or by embracing generics, Objective-C code will be more robust, less error prone, and Swift code that uses Objective-C can be safer.
Values marked as Nullable in Objective-C will be considered as Optionals in Swift. Typed Objective-C arrays will not be AnyObject arrays in Swift anymore. And that’s very good.
But still, what happens to id? Well, there are still two use cases for it:
- Store different types of values in a Dictionary.
- Type something as “any object implementing a protocol”
The second use case is something I have not done in many years (I always used to type pointers to protocols as NSObject <MyProtocol>).
The first one, is something that, although powerful, I always considered as a code smell.
So there you are, that’s the reason behind the post title.