I have an objective c library that can be used in Swift using the bridging header.
One of my public methods is annotated as returning nonnull
but in fact it can return nil in some cases.
I was expecting that a Swift code calling this method would crash because "unwrapping an nil optional value" but in fact it doesn't.
- (nonnull UserService *)users
{
if (!_users && [self checkStarted]) {
_users = [[UserService alloc] init];
}
return _users;
}
-(BOOL) checkStarted
{
return NO;
}
The generate header looks like this:
func users() -> UserService
let userService = sdk.users()
When I po
the returned value, I get this result
po userService
<uninitialized>
How come?
Maybe there is a misunderstanding: In many programming languages you can make many mistakes like annotating a value constraint and then not fulfilling it. I've read the C standard dozens of times, that contains many of such mistakes. The result is usually that you get a undefined behavior. It is not that the result is a definite crash. I have never read such a "promise". And it makes no sense.
So, simply said: The behavior is undefined. Undefined behavior includes the possibility that nothing crashes.
How can that happen?
Annotating non-null gives the compiler the oppertunity to make code better in some situations in others not. There might be an advantage the compiler can take through optimization. But of course there are situations in which the compiler cannot do so.
Since you get an Objective-C object, every message to that object has to be dispatched at run time. There is no way to do that at compile time (at least the methods can be replaced, methods can be overwritten in subclasses and so on) even you use that object in Swift. Dynamic Dispatching is the way Objective-C works, even if you put it in a Sift context.
So the Swift call becomes an Objective-C message. Objective-C messages are delivered by the Objective-C runtime and this can handle messages to nil. So there is no problem.
If something else happens with the object, you may get a crash. I. e. if the generated code tries to access the isa
pointer, you may get a null pointer exception.
Maybe. Maybe not. This is undefined.