在 Swift 中使用返回 Optional 或 Throw 的 Objective-C 函数

pbu*_*eit 5 objective-c throw optional swift bridging-header

我正在开发一个需要与现有 Objective-C api 交互的 swift 项目。不过,我在使用其中一个功能时遇到了一些障碍。在objective-c 头文件(OrderItem.h)中,我有这个函数定义:

+ (NSString *_Nullable)getOptional:(NSString *_Nonnull)foo error:(NSError *_Nullable *_Nullable)error;
Run Code Online (Sandbox Code Playgroud)

特别要注意最后一个参数;因为它是一个错误指针,在 swift 中调用此方法将需要包含在错误处理程序中(do .. catch)。

这是相应的 .m 文件:

+ (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;
    }
}
Run Code Online (Sandbox Code Playgroud)

在我的 swift 文件中,我添加了以下代码:

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);
    }

}
Run Code Online (Sandbox Code Playgroud)

没有什么特别复杂的;对 getOptional 的两次调用实际上都不应该导致错误。但是,当我运行该函数时,“123”案例正在爆炸并导致测试失败。当我仔细观察时,似乎我的 Objective-c 的桥接版本将返回类型定义为 Nonnull (-> OrderItem),即使我在 Objective-c 中明确将其定义为 Nullable。更奇怪的是,如果我在没有最后的“错误”参数的情况下声明相同的函数,那么桥接版本将具有正确的 Nullable 返回类型(-> OrderItem?)。

有人可以对这里发生的事情有所了解吗?更重要的是,有没有办法解决这个问题?

Ami*_*wad 6

在 Cocoa 中,有一种错误模式,即可能失败的方法将有一个返回值和一个间接错误参数。如果它是返回对象引用的方法,则模式为

\n\n
    \n
  • 设置间接错误参数指向的引用,

  • \n
  • 返回nil

  • \n
\n\n

所以看起来像这样

\n\n
+(NSString *) getOptional:( NSString *) foo error:(NSError *__autoreleasing *)error\n{\n   \xe2\x80\xa6\n   // Error case\n   *error = [NSError \xe2\x80\xa6];\n   return nil;\n   \xe2\x80\xa6\n }\n
Run Code Online (Sandbox Code Playgroud)\n\n

在 Swift 中,错误被转换为do\xe2\x80\xa6catch结构。nil因此,从 Swift 的角度来看,永远不会使用指示错误的返回值,因为执行被捕获。因此它是不可为空的。

\n