Search code examples
iosswiftswift3modulus

What does "% is unavailable: Use truncatingRemainder instead" mean?


I get the following error when using code for an extension, I'm not sure if they're asking to just use a different operator or modify the values in the expression based on an internet search.

Error: % is unavailable: Use truncatingRemainder instead

Extension code:

extension CMTime {
    var durationText:String {
        let totalSeconds = CMTimeGetSeconds(self)
        let hours:Int = Int(totalSeconds / 3600)
        let minutes:Int = Int(totalSeconds % 3600 / 60)
        let seconds:Int = Int(totalSeconds % 60)

        if hours > 0 {
            return String(format: "%i:%02i:%02i", hours, minutes, seconds)
        } else {
            return String(format: "%02i:%02i", minutes, seconds)
        }
    }
}

The error(s) occur when setting the minutes and seconds variables.


Solution

  • CMTimeGetSeconds() returns a floating point number (Float64 aka Double). In Swift 2 you could compute the remainder of a floating point division as

    let rem = 2.5 % 1.1
    print(rem) // 0.3
    

    In Swift 3 this is done with

    let rem = 2.5.truncatingRemainder(dividingBy: 1.1)
    print(rem) // 0.3
    

    Applied to your code:

    let totalSeconds = CMTimeGetSeconds(self)
    let hours = Int(totalSeconds / 3600)
    let minutes = Int((totalSeconds.truncatingRemainder(dividingBy: 3600)) / 60)
    let seconds = Int(totalSeconds.truncatingRemainder(dividingBy: 60))
    

    However, in this particular case it is easier to convert the duration to an integer in the first place:

    let totalSeconds = Int(CMTimeGetSeconds(self)) // Truncate to integer
    // Or:
    let totalSeconds = lrint(CMTimeGetSeconds(self)) // Round to nearest integer
    

    Then the next lines simplify to

    let hours = totalSeconds / 3600
    let minutes = (totalSeconds % 3600) / 60
    let seconds = totalSeconds % 60