One of the biggest differences between Objective-C and Swift is the handling of nullability. But since Xcode 6.3 there are two new keywords in Objective-C that improve their interoperability: nullable and nunnull.
Interoperability problems between Objective-C and Swift
If you are interacting with Objective-C API from Swift, you are confronted with one big problem: Objective-C pointers are allowed to be nil, whereas in Swift only Optionals can be nil. So for the compiler only two options remain to translate the Objective-C header file to Swift:
- Importing the Objective-C pointers as optionals
- Importing the Objective-C pointers as implicit unwrapped optionals, that means they are actually optionals but you are not forced to unwrap them
Both ways have their disadvantages: If a pointer is imported as an optional, you must unwrap it. Most of the times, this would not be necessary, because from the context it could be clear that is not nil. That leads us to option number two – implicit unwrapping. But even if you can be sure from the context that the pointer is not nil in some cases, there will be situations when they will be actually nil. And because you are not forced to check it there is the danger of a runtime crash.
So it would be nice if the compiler would know if a Objective-C pointer could be nil, wouldn’t it?
New nullability keywords
The solution to this problem are two Objective-C keywords: nullable and nonnull . You can use these keyword for example for properties, method return values and method arguments. If you use the nonnull keyword, the value will not be optional if you are accessing it from Swift code. On the other hand, if you use nullable , then it is accessible as an optional.
Let’s take a look at an example:
@interface ObjectiveCTestClass : NSObject @property (nonatomic,strong) NSString* testString; @property (nonatomic,strong,nonnull) NSString* testStringNonnull; @property (nonatomic,strong,nullable) NSString* testStringNullable; - (NSString*)testFunctionWithTestString:(NSString*)testString; - (nonnull NSString*)testFunctionNonnullWithTestString:(nonnull NSString*)testString; - (nullable NSString*)testFunctionNullableWithTestString:(nullable NSString*)testString; @end
If we define this class in a bridging header file and try to call these properties and methods from a Swift class, we will get the following:
As you can see, the objects without a nullability keyword (e.g. testString) are imported as implicit unwrapped optionals. If you are using the nonnull keyword (e.g. testStringNonnull) they are non-optionals and if you are using the nullable keyword (e.g. testStringNullable) they are optionals.
[thrive_text_block color=”blue” headline=”Conclusion”]
The nullability keywords are a big help if you are dealing with Objective-C from Swift. And since the whole iOS SDK is written in Objective-C, that will be very often the case. But also for your own code it is very advisable to use this feature. But it has also its downsides: Within Objective-C these keywords make no difference at all – so your Objective-C code will not become nicer. But you can’t have your cake and eat it – can you?
Using Swift with Cocoa and Objective-C
Image: @ Fer Gregory / Shutterstock.com