Obj-C非空函数返回Swift的是什么?

时间:2016-10-17 17:27:36

标签: objective-c swift objc-bridging-header

我有一个可以使用桥接头在Swift中使用的目标c库。

我的一个公共方法被注释为返回nonnull但实际上在某些情况下它可以返回nil。

我原以为调用此方法的Swift代码会崩溃,因为“展开一个nil可选值”,但实际上并没有。

目标C:

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

-(BOOL) checkStarted
{
    return NO;
}

Swift Header:

生成标题如下所示:

func users() -> UserService

Swift用法:

let userService = sdk.users()

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

po userService
<uninitialized>

怎么回事?

1 个答案:

答案 0 :(得分:0)

也许存在一个误解:在许多编程语言中,你可以犯很多错误,比如注释一个值约束,然后就不会实现它。我已经读了几十次C标准,其中包含很多这样的错误。结果通常是您得到一个未定义的行为。结果不是一个明确的崩溃。我从来没有读过这样的“承诺”。这没有任何意义。

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

怎么会发生这种情况?

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

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

因此Swift调用成为Objective-C消息。 Objective-C消息由Objective-C运行时提供,这可以处理消息为nil。所以没有问题。

如果对象发生其他事情,您可能会崩溃。 I. e。如果生成的代码试图访问isa指针,则可能会出现空指针异常。

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