2

Is it possible to use optional chaining and nil coalescing simultaneously like so?

print("Meeting host: " + meeting.host?.email ?? “No host”)

I'd like to do this but I get an error saying that my String? is not unwrapped. email is a non optional String.

Is this possible without having to unwrap host before hand and if not why does my attempt at doing this not work?

Declan McKenna
  • 4,321
  • 6
  • 54
  • 72
  • 1
    If you get an "unexpected" compiler error, divide the expression into smaller parts. In your case: Start with `let host = meeting.host?.email ?? "No host" ; print("Meeting host: " + host)` – You'll notice that that compiles, so the optional chaining and nil-coalescing works generally. – Martin R Jul 27 '17 at 13:52
  • 1
    See here, https://stackoverflow.com/a/44877393/6479530 – Rajamohan S Jul 27 '17 at 13:57

2 Answers2

5

You don't have to unwrap it to get it to work. That is not why the error occurred. The ?? is designed to handle such cases, after all.

The error occurs because of operator precedence. The compiler thinks that it should evaluate the + first, concatenating the two strings, THEN do the nil-coalescing. It sees that the second operand is not unwrapped and complains.

To make it produce the intended result, explicitly tell the compiler to evaluate the ?? first by adding brackets:

print("Meeting host: " + (meeting.host?.email ?? “No host”))
Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • 1
    Note that using `+` this way can explode compile times. Strongly avoid `+` with strings; it's the #1 cause of "my Swift takes too long to compile" questions. One is fine, but even two or three lead to exponential problems. Get in the habit of string interpolation: `print("Meeting host: \(meeting.host?.email ?? "No host")")` This also happens to get rid of the precedence problem Sweeper explains so well. – Rob Napier Jul 27 '17 at 13:55
  • 2
    print() takes a variable number of arguments, so one can also write `print("Meeting host:", meeting.host?.email ?? "No host")` – Martin R Jul 27 '17 at 13:57
1

There is an easier solution for this:

class Host {
    var email: String?
}

var host: Host? = nil
print("Meeting host: " + String(describing: host?.email))

The output is:

Meeting host: nil

Oleg Danu
  • 4,149
  • 4
  • 29
  • 47