Conditional unwrap

The function we created earlier returns an optional value, so if you want to do anything useful with the resulting value, we need to unwrap the optional. So far, the only way to do this is by force unwrapping, which will cause a crash if the value is nil.

Instead, we can use an if statement to conditionally unwrap the optional, turning it into a more useful, non-optional value.

Let's create a function that will print information about a pool ball of a given number. If the provided number is valid for a pool ball, it will print the ball's number and type; otherwise, it will print a message explaining that it is not a valid number.

Since we will want to print the value of the PoolBallType enum, let's make it String backed, which will make printing its value easier:

enum PoolBallType: String {
case solid
case stripe
case black
}

Now, let's write the function to print the pool ball details:

func printBallDetails(ofNumber number: Int) { 
let possibleBallType = poolBallType(forNumber: number)
if let ballType = possibleBallType {
print("\(number) - \(ballType.rawValue)")
} else {
print("\(number) is not a valid pool ball number")
}
}

The first thing we do in our printBallDetails function is to get the ball type for the given number:

let possibleBallType = poolBallType(forNumber: number) 

In our improved version of this function, this returns an optional version of the PoolBallType enum. We want to include the rawValue of the returned enum as part of printing the ball details, but we need to unwrap it to do that:

if let ballType = possibleBallType { 
print("\(number) - \(ballType.rawValue))")
}

In this if statement, instead of defining a Boolean expression, we are assigning our optional value to a constant; the if statement uses this to conditionally unwrap the optional. The value of the optional is checked to see whether it is nil ; if it is not nil, then the value is unwrapped and assigned to the constant as a non-optional value; that constant is now available within the scope of the curly brackets following the if statement. We use that ballType non-optional value to obtain the raw value for the print statement.

Since the if branch of the if-else statement is followed when the optional value is non-nil, the else branch is followed when the optional value is nil:

else { 
print("\(number) is not a valid pool ball number")
}

Since this means that the given number is not valid for a pool ball, we print a relevant message.

Now we can insert any integer and print ball correct details:

printBallDetails(ofNumber: 2)  // 2 - solid
printBallDetails(ofNumber: 8) // 8 - black
printBallDetails(ofNumber: 12) // 12 - stripe
printBallDetails(ofNumber: 0) // 0 is not a valid pool ball number
printBallDetails(ofNumber: 16) // 16 is not a valid pool ball number