My principle work projects and my own side projects do not (yet) contain any Swift.
This is NOT because I do not like Swift or that I think it's the future. In my case it's because the apps I work on for my employer have a solid objective-c grounding and there's much work to do polishing and adding features before we consider a transition. A great example is that we shipped a port for Apple TV for the launch of the new 4th gen; because so much of it was shared with the iOS version, it just made sense given the deadline to stick with obj-c for now.
But I'm conscious of wanting to transition at some point and that there are two areas I need to address to prepare:
- Is my Objective-C code going to integrate well with Swift?
- I need to understand more about the mindset behind Swift programming.
Luckily there's a couple of great things I can start to add to my current codebase that do BOTH of these things! Objective-C Generics and Nullability specifiers.
So, generics. When this got announced as part Swift I got it. Mostly. I've done some C++ after all and the concept was sound. I understand *why* they're called generics, it allows you to be generic about the type of an object you pass/receive, but it helped my understanding a lot to instead think of them as 'specifics'.
I'm being specific about the exact nature of the objects I'm using, they're base object type and the things they conform to.
Start adding these to your objective-c code now! It'll make your code look pretty crazy but it'll be interesting see how many things that the compiler and static analyzer find that could crash at runtime. If you took some time to retrofit an older codebase with generics then you'll have a very solid understanding of where they fit in the Swift world.
Here's an example of some code where I added generics...
- (void)netServiceBrowser:(NSNetServiceBrowser *)browser didNotSearch:(NSDictionary<NSString *,NSNumber *> *)errorDict;
See how the NSDictionary is explicit about the types of the keys and values (NSString and NSNumber respectively).
Interesting syntax, right? Now imagine adding a generically typed array of arrays...
+ (NSArray<NSArray <NOTLayoutItem *> *> *)itemsForThings:(NSArray<NSNumber *> *)filters;
Mmmmm, lovely. So it messes with the readability a bit for the unfamiliar but the advantages outweighs that.
Learn more about generics here.
These allow you to be very specific about whether you can pass or receive a nil value as an argument to a method. Honestly, I found that the difference in syntax between specifying the nullability for arguments and return values means that like block syntax, I need to look it up everytime. Secondly, Xcode takes an all or nothing approach to them which means if you add them to any part of a header file, it's going to want you to specify them for every argument and return type. So you can end up with some very verbose method declarations:
- (__nonnull instancetype)initWithServiceName:(nullable NSString *)name domain:(nonnull NSString *)domain type:(nullable NSString *)type protocol:(NOTBonjourServiceProtocol)protocol serviceMask:(NOTBonjourServiceMask)types pathToData:(nullable NSString *)pathToData;
See how there's a mix of nullability and non-nullability in the arguments? And I left out the Generics specifiers. For clarity. Thankfully there's some gems defined in the objective-c runtime that you can employ to make the compiler assume that everything unspecified will be considered non-nullable.
Wrap you're header code inside...
NS_ASSUME_NONNULL_BEGIN // ...interface begin and end NS_ASSUME_NONNULL_END
These are #defines for some pragma clang pre-processor directives. Now all you have to do is be specific when something IS nullable.
For more information on nullability specifiers go to the horses mouth.
Embrace these in your existing code and they'll help you mentally prepare for the paradigm shift of Swift and put your existing code in a good place for interoperability.