Yes, force unwrapping is ok if you're 100% sure the value won't be nil, but this should only be used when, for code structure reasons, you can't do otherwise. The thing is, most of the times, you can do otherwise, so using force-unwrapping should rarely happen. In your case, I think most of it can be refactored.
For example: why are your variables x
and y
declared as Optionals in the first place? Do they have to be?
If they are only used in this method, they should not be declared as Optional, and they should be declared inside the method, not outside.
If they are used elsewhere, they should be declared as Optional only if you know they will be nil at some point (which means that they should not be force unwrapped when used, but instead properly validated with error handling).
If they are used elsewhere and won't be nil when used, but you declared them as Optional for structural reasons, then you could use an implicitly unwrapped Optional instead.
private var x: Int!
private var y: Int!
This way you won't have to force unwrap them each time you use them.
Also, if this is acceptable in your context, you could make them non-optional and have an initial value.
private var x: Int = 0
private var y: Int = 0
But let's say that you have a good reason to declare them as Optionals. In this case, you still can improve your code by safely unwrapping the variables before using them.
guard let x = Int(ceil(sqrt(Double(rooms!)))) else {
// show some message
return
}
That way, if the user types a letter, space or non-numeric character, instead of a number, the app won't crash.
Maybe you're making sure elsewhere that the user can only input a number? In this case, force unwrap x
before using it:
x = Int(ceil(sqrt(Double(rooms!))))!
Now, actually, the issue might only happen if numberOfRooms
is not a number, so this unwrapping should happen earlier.
guard let numberOfRooms = selectedRooms.text, !numberOfRooms.isEmpty, let rooms = Int(numberOfRooms) else {
// error message 'please input a number'
return
}
Same idea about currentX
and currentY
: why are these declared as Optionals? Can the getRandom
method return nil? Maybe that can be changed?
Same for maze
: if MazeGenerator
can return nil, the shouldn't you handle possible errors instead of force unwrapping? And if it won't ever return nil, then why does it return an Optional instead of a normal value? (or maybe it doesn't return an Optional and the issue is that maze
was declared as an Optional but shouldn't have been).
These are the issues you should address.
While force unwrapping is indeed not bad if you can guarantee the value won't be nil when you use it, most of the times it's better to make sure earlier in the code flow that the value won't be nil, which will allow you to not having to use Optionals.
In short: validate the values before use, abort and show an error message if the content is incorrect at the validation step, and then proceed to use the values without having to use Optionals and unwrapping.