Search code examples
iosswift3imessage-extension

Can a non-optional type be nil?


In a MessagesViewController, we are using the overridden delegate methods. When sending a message, didStartSending is called as expected. The non-optional parameter message is nil though:

override func didStartSending(_ message: MSMessage, conversation: MSConversation) {
    if message != nil { 
        logInfo("didStartSending message: \(message) conversation: \(conversation)") 
    } else { 
        logInfo("didStartSending message: \("why nil") conversation: \(conversation)") 
    }
}

Log:

"didStartSending message: why nil conversation: <MSConversation: 0x17026ca00>"

Debugging with po:

(lldb) po message 
    <uninitialized>

Also we get the expected warning on the if line:

Comparing non-optional value of type MSMessage to nil always returns true

The same is true for didCancelSending.

How can a non-optional, which can not be nil by definition in my understanding, actually be nil.


Solution

  • The compiler will try hard to make it impossible that a non-optional value is ever nil. I think you can get past the compiler by declaring an Objective-C function as nonnull and then making it return nil. If you do that, then all odds are off. Anything can happen.

    I haven't tried if comparing a non-optional with nil is legal or not; if it is legal then the compiler is allowed to assume that the comparison will always return "false"; so checking that a non-optional that should never be allowed to be nil is actually nil or not will not work.

    I see you checked it... So comparing non-optional and nil is legal, but the compiler assumes they will never be the same and warns you.