I have this function:
func getSeconds()->Int{
return Int(Double(self.value) * (self.player.currentItem?.duration.seconds)!)
}
It sometimes crashes:
Fatal error: Double value cannot be converted to Int because it is either infinite or NaN
Of course I've seen this:
Swift 3:fatal error: Double value cannot be converted to Int because it is either infinite or NaN
But how EXACTLY do I have to use this?
What is this?:
guard !(totalSeconds.isNaN || totalSeconds.isInfinite) else {
return "illegal value"
}
Where do I return totalSeconds
if everything is fine?
EDIT:
I'm doing it like this now:
func getSeconds()->Int{
let totalSeconds = self.player.currentItem?.duration.seconds
if(totalSeconds != nil){
guard !(totalSeconds!.isNaN || totalSeconds!.isInfinite) else {
return 0 // or do some error handling
}
return Int(Double(self.value) * (self.player.currentItem?.duration.seconds)!)
}else{
return 0
}
}
Does it make sense?
As mentioned in the answer to the question you linked to, the code is there to verify that the value is a valid number.
Your edit is in the correct direction but it could use some improvements to the handling of optionals. Something like the following might be better:
func getSeconds() -> Int {
guard let totalSeconds = self.player.currentItem?.duration.seconds,
!totalSeconds.isNaN && !totalSeconds.isInfinite else { return 0 }
return Int(Double(self.value) * totalSeconds)
}
The guard
first gets the value of self.player.currentItem?.duration.seconds
but only if there is a non-optional value. If self.player.currentItem
is currently nil then there won't be a duration.
Once the guard
gets a value in seconds, it makes sure the value is neither NaN nor infinite.
So the guard
's else
will be reached if there is no current item to get the duration for, or if the duration isn't a finite number.
If you have a good number, the code can move on the calculation and return a final value.
Note there is no use of force-unwraps in the code. You should avoid those to eliminate likely crashes. Learning proper optional handling in Swift is critical.
As stated in a comment to the answer you referenced, the whole !(totalSeconds.isNaN || totalSeconds.isInfinite)
can be written as totalSeconds.isFinite
. Doing that in your function would change the guard
to be:
guard let totalSeconds = self.player.currentItem?.duration.seconds,
totalSeconds.isFinite else { return 0 }
This is a bit easier to read and more to the point of the needed check in this case.