TL;DR: Why is an Objectiv-C object created as Swift Optional when assigned to a var before returning it as func result and as Non-Optional when returning it directly?
Details:
I would like to use some existing Objectiv-C code in Swift. A Swift methods creates and returns an UIViewController
. This does not work as expected when working with a UIViewController
class implemented in Objectiv-C
// SomeViewController.h
@interface SomeViewController : UIViewController { }
- (id)initWithData:(MyData *)data;
@end
// SomeViewController.m
@implementation SomeViewController { }
- (id)initWithData:(MyData *)data {
self = [super init];
if (self) {}
return self;
}
@end
// Swift
func foo() -> UIViewController {
return SomeViewController(data: someData) // Works fine
}
func foo() -> UIViewController {
// ERROR: Value of optional type 'SomeViewController?' must be
// unwrapped to a value of type 'SomeViewController'
let vs = SomeViewController(data: someData)
return vc
---
// No problem when using standard init
let vs = SomeViewController()
return vc // Works fine
}
2
Answers
Because the initialization method provided by the CocoaTouch frameworks can never be return nil value。However, custom initializers method can return nil value。
for example
// SomeViewController.h
or overwrite init method
Xcode BUG
error message
Objective-C initializers can return
nil
unless you specify otherwise in the initializer’s declaration, so Swift has no choice but to infer its type to beOptional
.The easiest way to specify non-nullability is to bracket your
.h
file with nullability assumptions:The reason that the built-in initializers don’t infer type as optional is because they have all been audited and explicitly declared to be either nullable on non-nullable.
More details: https://developer.apple.com/swift/blog/?id=25