Obj-C 非空函数 returns 到 Swift 的作用是什么?

What does a Obj-C nonnull function returns to Swift?

我有一个 objective c 库,可以在 Swift 中使用桥接 header。

我的一个 public 方法被注释为 returning nonnull 但实际上在某些情况下它可以 return nil。

我原以为调用此方法的 Swift 代码会崩溃,因为 "unwrapping an nil optional value" 但实际上并没有。

Objective-C:

- (nonnull UserService *)users
{
    if (!_users && [self checkStarted]) {
        _users = [[UserService alloc] init];
    }
    return _users;
}

-(BOOL) checkStarted
{
    return NO;
}

Swift Header:

生成的 header 看起来像这样:

func users() -> UserService

Swift 用法:

let userService = sdk.users()

当我 po returned 值时,我得到了这个结果

po userService
<uninitialized>

怎么会?

也许有一个误解:在许多编程语言中,你可能会犯很多错误,比如注释一个值约束然后不满足它。我已经阅读了数十次 C 标准,其中包含许多此类错误。结果通常是您得到未定义的行为。这并不是说结果肯定会崩溃。我从来没有读过这样的"promise"。这毫无意义。

所以,简单地说:行为是 未定义。未定义的行为包括没有崩溃的可能性。

怎么会这样?

注释非 null 为编译器提供 机会 使代码在某些情况下更好,而在其他情况下则不然。 可能 是编译器可以通过优化获得的优势。但当然也有编译器不能这样做的情况。

由于您获得了一个 Objective-C 对象,因此必须在 运行 时间发送到该对象的每条消息。在编译时没有办法做到这一点(至少方法可以被替换,方法可以在子类中被覆盖等等)即使你在 Swift 中使用那个对象。动态调度是 Objective-C 的工作方式,即使您将它放在 Sift 上下文中也是如此。

因此 Swift 调用变成了 Objective-C 消息。 Objective-C 消息在 Objective-C 运行 时间内传送,这可以将消息处理为零。所以没有问题。

如果对象出现其他问题,您可能会崩溃。 IE。如果生成的代码试图访问 isa 指针,您可能会遇到空指针异常。

也许吧。也许不吧。这是未定义的。