I'm working on a swift project that need to interact with an existing objective-c api. I've run into a bit of a roadblock with one of the functions though. In the objective-c header file (OrderItem.h) I have this function definition:
+ (NSString *_Nullable)getOptional:(NSString *_Nonnull)foo error:(NSError *_Nullable *_Nullable)error;
In particular, take notice of the last parameter; because it is an error pointer calls to this method in swift will need to be wrapped in an error hander (do .. catch).
Here is the corresponding .m file:
+ (NSString *)getOptional:(NSString *)foo error:(NSError *__autoreleasing *)error
{
if([foo isEqualToString:@"abc"])
{
return @"abc item";
}
else
{
if([foo isEqualToString:@"xyz"])
{
*error = [[NSError alloc] init];
}
return nil;
}
}
In my swift file I then added this code:
func testGetOptional()
{
do
{
var result:NSString? = try OrderItem.getOptional("abc");
XCTAssertNotNil(result);
result = try OrderItem.getOptional("123");
XCTAssertNil(result);
}
catch let error as NSError
{
XCTFail("OrderItem lookup should not have thrown an error. Error was " + error.localizedDescription);
}
}
Nothing especially complicated; neither of the two calls to getOptional should actually result in an error. When I run that function however, the '123' case is blowing up and causing the test to fail. When I took a closer look, it seems that the bridged version of my objective-c is defining the return type as Nonnull (-> OrderItem) even though I explicitly defined it as Nullable in the objective-c. Even more strange, if I declare this same function without the final 'error' parameter then the bridged version will have the correct return type of Nullable (-> OrderItem?).
Can someone shed some light on what is going on here? More importantly, is there some way to work around this issue?
In Cocoa there is the error pattern that a method that can fail will have a return value and an indirect error parameter. If it is a method returning a object reference, the pattern is
set the reference the indirect error argument points to,
return nil
So it looks like this
+(NSString *) getOptional:( NSString *) foo error:(NSError *__autoreleasing *)error
{
…
// Error case
*error = [NSError …];
return nil;
…
}
In Swift errors are translated into a do
… catch
construct. Therefore a return value of nil
signaling an error is never used from the Swift point of view, because the execution is caught. Therefore it is non-nullable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With