Swift and Objective-C Interoperability
I’ve stumbled on an issue while working on my hobby project. One of the few related to Swift and Objective-C interoperability.
Let’s setup a simple code base.
There’s pure Swift enum, protocol and a subclass of Objective-C class that adopts pure Swift protocol. By the way, have you ever tried declaring Swift enum with just one case?
Further on, I declare a generic class with type conforming to pure Swift protocol.
So what happens if I pass an Objective-C subclass to this generic class initializer?
To be honest, nothing happens most away. For reasons unknown to me my project compiled and ran. And it was running OK for a while until at some moment it started crashing consistently.
So the problem in this case is that I’m implicitly checking the conformance of Objective-C object
ObjCSubclass to a non Objective-C (pure Swift) protocol
PureSwiftProtocol. This check occurs when calling
return embeddedInstance.value where
embeddedInstance is an instance of
ObjCSubclass but the access to it’s property happens by converting it to
Solution A: Back to Roots
The first solution is to turn
PureSwiftProtocol into Objective-C protocol by using
But that won’t make compiler happy because it has no idea how to map
PureSwiftEnum into Objective-C. So you have to take it one step further. You have to declare
PureSwiftEnum as Objective-C enum (with
NS_ENUM), obviously you have to do it in Objective-C header file and properly setup bridging header in your project.
Solution B: Wrap it Up
If you don’t want to revert back to adding Objective-C code with the hope that Apple eventually fixes this issue in the future, you can try another ugly trick - wrap your Objective-C class with pure Swift class that conforms to the same protocol.
Now you can pass an instance of
With this setup my crash went away and hadn’t reappeared since then.
Reference to objc-interop.swift to experiment and run it from command line or in Playground
blog comments powered by Disqus