5 things you can do with Objective-C but can’t do with pure Swift
I like programming in Swift as much as I like programming in Objective-C or Python or C#, therefore this post is not intended to favour between the two languages; I will try to cover things you can do with Swift, but can’t do with Objective-C in a later post.
Having said that, after writing Objective-C for a long time, sometimes there are tools that seem to be missing when programming in pure Swift, even though there are usually ways of getting more or less the same results with using just Swift. A lot of apps and frameworks written in Objective-C are dependent on these tools, and sometimes hacks, that make our code more concise and easier to work with. I will start my list with probably the most controversial topic in Objective-C.
1.) Method Swizzling
Swizzling is controversial because it allows you to change the behaviour of your classes at runtime by changing the implementation of their selectors. This means you could potentially have a service that gives you a class name or a method name as a string, and change the way your app behaves at runtime. Pure Swift classes which don’t inherit from
NSObject, with the methods we want to swizzle marked as
@dynamic lack this ability, but being an inherently less dynamic and a type safe language is what is appealing to most Swift developers in the first place.
There are many Objective-C frameworks / libraries out there that use method swizzling to make our lives easier and code cleaner.
Aspects is a powerful library that uses swizzling to make Aspect Oriented Programming possible in Objective-C. This enables you to implement non-invasive code for things like app analytics, as seen in another library ARAnalytics. OCMock is heavily dependent on Objective-C runtime and is not really supported with Swift.
Rollout.io use method swizzling to push live updates to your apps. An interesting development has taken place at Rollout.io where they describe how they even do live updates with Swift apps!
2.) C++ Interop
Objective-C supports interoperability with C++ code via a construct named Objective-C++. There are many projects / libraries out there that use C++ for its core components, in order to be able to ship cross-platform versions of the library faster, rather than rewriting the whole library in platform’s native language. Good examples of these are PSPDFKit and Realm.
Of course you can wrap your C++ code in C or Objective-C, and then talk to that code via Swift, but it adds to the amount of code and maintenance in your code base.
performSelector: is an instance method of
NSObject class that sends a specified message to the receiver and returns the result of the message. Making a method call on such an object triggers a chain of events that invokes the
objc_msgSend function (which is also unavailable in Swift). This function looks up if there is an implementation present for that class` method call, if not, it goes up the chain to superclass, until it comes to the root level at
NSObject where it throws an
unrecognized selector sent to instance
NSInvalidArgumentException. This mechanism allows you to send messages to objects without knowing their type upfront, like so:
Class personClass = NSClassFromString(@"Person");
id object = [personClass new];
NSString *name = [object performSelector:NSSelectorFromString(@”name”)];
You could use this tool for instance to grab some info from a web service, and then execute a different code path in the app, based on the response, by parsing the selector name you want to call.
This kind of behaviour is not supported in pure Swift classes which don’t inherit from
NSObject, and for a good reason, because it can lead to undesired consequences in your code. Apple documentation for
Because of the inherent lack of type safety, this API is not recommended for use in Swift unless your code specifically relies on the dynamic method resolution provided by the Objective-C run-time.
You could for instance accidentally add an object you don’t want in an array you are iterating over and call a selector on that object that it doesn’t conform to, which would throw an
NSException, or the method of that object could be returning a different type than you would expect, or even
nil, leading to unpredictable behaviour in your application.
Also unavailable in Swift is
NSInvocation, a Cocoa implementation of command pattern, which allows you to store and forward messages between objects and between applications.
Key-value observing provides a mechanism that allows objects to be notified of changes to specific properties of other objects, as defined in official Apple Documentation. KVO is a powerful mechanism, which makes observing state changes really easy to implement, albeit through a horrible interface. Again, pure Swift classes that don’t inherit from
NSObject and have observable properties marked as
@dynamic lack this ability.
However, there are many open source libraries out there to help with that. Most reactive programming frameworks like RxSwift and ReactiveCocoa are here to help with their own observable constructs, or you can even build your own Observable type.
5.) Complex Macros
A macro is a fragment of code which has been given a name, as defined by GCC community. Macros have been around for a long time and are well known to be used in languages like C and C++. But what would you use a Macro for when writing your app?
The most trivial use of a Macro you can find in any app written in Objective-C is probably different debug logging applications, or ios version number checking macros.
Some libraries like libextobjc use macros to extend the capabilities of the language itself, while others like Nimble use it to create a domain specific language (DSL), in order to make the API-s more user friendly.
Of course all of these functionalities are probably outdated in Swift, where you can create beautiful API-s by composing functions.
This is not a final and definitive list, it’s a list I’ve made from my own experience, and the tools I have been using a lot in my previous and current projects. If you find any errors, or have any suggestions on how to improve this list, please leave a comment.
Thanks for reading!