我有一个可以使用桥接头在Swift中使用的目标c库。
我的一个公共方法被注释为返回nonnull
但实际上在某些情况下它可以返回nil。
我原以为调用此方法的Swift代码会崩溃,因为“展开一个nil可选值”,但实际上并没有。
- (nonnull UserService *)users
{
if (!_users && [self checkStarted]) {
_users = [[UserService alloc] init];
}
return _users;
}
-(BOOL) checkStarted
{
return NO;
}
生成标题如下所示:
func users() -> UserService
let userService = sdk.users()
当我po
返回值时,我得到了这个结果
po userService
<uninitialized>
怎么回事?
答案 0 :(得分:0)
也许存在一个误解:在许多编程语言中,你可以犯很多错误,比如注释一个值约束,然后就不会实现它。我已经读了几十次C标准,其中包含很多这样的错误。结果通常是您得到一个未定义的行为。结果不是一个明确的崩溃。我从来没有读过这样的“承诺”。这没有任何意义。
所以,简单地说:行为是 undefined 。未定义的行为包括没有任何事情崩溃的可能性。
怎么会发生这种情况?
注释非null为编译器提供了 oppertunity ,以便在某些情况下使代码更好。 可能是编译器可以通过优化获得的优势。但是当然有些情况下编译器不能这样做。
由于您获得了Objective-C对象,因此必须在运行时调度该对象的每条消息。在编译时没有办法做到这一点(至少可以替换方法,可以在子类中覆盖方法等),即使你在Swift中使用该对象。动态调度是Objective-C的工作方式,即使你把它放在Sift上下文中也是如此。
因此Swift调用成为Objective-C消息。 Objective-C消息由Objective-C运行时提供,这可以处理消息为nil。所以没有问题。
如果对象发生其他事情,您可能会崩溃。 I. e。如果生成的代码试图访问isa
指针,则可能会出现空指针异常。
也许。也许不吧。这是未定义的。