Dante May Code
Dante May Code

Reputation: 11247

Why does String implicitly become String! in Swift

I received a compilation error from Xcode yesterday, saying

Binary operator '&&' cannot be applied to two Bool operands [1]

on

if text != nil && presentingViewController != nil {
    ...
}

text is defined earlier as

var text: String = "" {
    didSet {
        ...
    }
}

and presentingViewController is from UIViewController, which is the super class.

A friend of mine told me that it was caused by text, which was of String!, and the issue was solved by changing

var text: String

to

var text: String?

However, it still puzzles me why my explicitly defined String becomes String!. Can anyone provide any detail on this implicit conversion?

[1] This compilation error does not make sense, and this question is not a duplicate of another question of the same compilation error.

Upvotes: 0

Views: 853

Answers (3)

phlebotinum
phlebotinum

Reputation: 1130

Your problem is related to what is called "optionals" in swift.

In Objective-C you could have a reference to NSString and it could either be pointing to an NSString instance - or to nil. In swift this is different!

A "regular" String in swift can never be nil. Only an "optional" String can be nil. This is how it would look in swift code:

var myRegularString  : String      // this can never be nil, can't compare to nil
var myOptionalString : String?     // this can be nil (note the ?)

You have a "regular" String. So the compiler complains when you try to compare it to nil.

Optionals are explained here: Swift Programming Language/Basics/Optionals

Upvotes: 2

gnasher729
gnasher729

Reputation: 52538

Your friend most certainly didn't solve your problem, he just glossed over it.

You declared an instance variable of type String. text will always be a String. It can never, ever be nil. Asking "text != nil" is pointless because it cannot be nil. It doesn't even compile, because a String, always being nil, cannot even checked for being nil.

Your friend suggested to use String? or String!. That's in your situation total nonsense. You have text which is guaranteed to be always a String. Instead you change it to text which may be a String or nil. This doesn't help you in any way. Yes, now you can ask it whether it is nil. Before, you didn't even have to ask.

Upvotes: 1

Matteo Piombo
Matteo Piombo

Reputation: 6726

Your explicitly defined String is not String! is ... String. Simple like that ;-)

String! is an implicitly unwrapped Optional<String>

String? is an Optional<String>

Optional<T> means that it can be a value of type T or Nothing (and nothing can be compared to nil).

Thus when you declare:

var text = ""

you declare an actual String and it cannot be nil. That's why the compiler is complaining: a String cannot be Nothing. Think of it as comparing a String with a CGFloat ... the compiler will complain.

Since String! is an Optional<String> than it can be compared against nil. The ! simply is you declaring that you are absolutely sure it is not Nothing such that you can use text without unwrapping its actual value.

BTW, do not confuse and empty String (i.e.: "") with Nothing. var text = "" is an actual String just empty and it is not comparable with Nothing

Hope this helps.

Upvotes: 2

Related Questions