operator ios swift xcode swift3 modulus

ios - operator - ¿Qué significa "% no está disponible: use truncatingRemainder en su lugar"?



swift 4 operators (4)

Recupere la sintaxis simple del módulo en Swift 3:

Esta sintaxis se sugirió realmente en la lista de correo rápida oficial de Apple here pero por alguna razón optaron por una sintaxis menos elegante.

infix operator %%/*<--infix operator is required for custom infix char combos*/ /** * Brings back simple modulo syntax (was removed in swift 3) * Calculates the remainder of expression1 divided by expression2 * The sign of the modulo result matches the sign of the dividend (the first number). For example, -4 % 3 and -4 % -3 both evaluate to -1 * EXAMPLE: * print(12 %% 5) // 2 * print(4.3 %% 2.1) // 0.0999999999999996 * print(4 %% 4) // 0 * NOTE: The first print returns 2, rather than 12/5 or 2.4, because the modulo (%) operator returns only the remainder. The second trace returns 0.0999999999999996 instead of the expected 0.1 because of the limitations of floating-point accuracy in binary computing. * NOTE: Int''s can still use single % * NOTE: there is also .remainder which supports returning negatives as oppose to truncatingRemainder (aka the old %) which returns only positive. */ public func %% (left:CGFloat, right:CGFloat) -> CGFloat { return left.truncatingRemainder(dividingBy: right) }

Este sencillo consejo de migración de swift 3 es parte de una guía de migración de swift 3 más completa con muchas ideas (35k loc / 8 días de migración) http://eon.codes/blog/2017/01/12/swift-3-migration/

Recibo el siguiente error cuando uso el código para una extensión, no estoy seguro de si están pidiendo usar un operador diferente o modificar los valores en la expresión en función de una búsqueda en Internet.

Error:% no está disponible: utilice truncatingRemainder en su lugar

Código de extensión:

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) } } }

Los errores se producen al configurar las variables de minutos y segundos.


Descubrí que lo siguiente funciona en Swift 3:

let minutes = Int(floor(totalSeconds / 60)) let seconds = Int(totalSeconds) % 60

donde totalSeconds es un TimeInterval ( Double ).


El operador % modulus se define solo para tipos enteros. Para los tipos de punto flotante, debe ser más específico sobre el tipo de comportamiento de división / resto IEEE 754 que desea, por lo que debe llamar a un método: remainder o truncatingRemainder . (Si está haciendo matemática de punto flotante, realmente necesita preocuparse por esto y muchas otras cosas , o puede obtener resultados inesperados / malos).

Si realmente tiene la intención de hacer un módulo entero, debe convertir el valor de retorno de CMTimeGetSeconds a un entero antes de usar % . (Tenga en cuenta que si lo hace, eliminará los segundos fraccionarios ... dependiendo de dónde esté usando CMTime que puede ser importante. ¿Desea minutos, segundos, cuadros, por ejemplo?)

Dependiendo de cómo desee presentar los valores de CMTime en su interfaz de usuario, puede ser mejor extraer el valor de segundos y pasarlo a NSDateFormatter o NSDateComponentsFormatter para obtener el soporte local adecuado.


CMTimeGetSeconds() devuelve un número de coma flotante ( Float64 también Float64 como Double ). En Swift 2, podría calcular el resto de una división de coma flotante como

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

En Swift 3 esto se hace con

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

Aplicado a su código:

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

Sin embargo, en este caso particular, es más fácil convertir la duración a un entero en primer lugar:

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

Entonces las siguientes líneas se simplifican a

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