iOS: ¿Cómo convertir UIViewAnimationCurve a UIViewAnimationOptions?

UIKeyboardAnimationCurveUserInfoKey tiene un valor UIViewAnimationCurve . ¿Cómo lo convierto al valor UIViewAnimationOptions correspondiente para utilizarlo con el argumento de options de +[UIView animateWithDuration:delay:options:animations:completion:] ?

 // UIView.h typedef enum { UIViewAnimationCurveEaseInOut, // slow at beginning and end UIViewAnimationCurveEaseIn, // slow at beginning UIViewAnimationCurveEaseOut, // slow at end UIViewAnimationCurveLinear } UIViewAnimationCurve; // ... enum { // ... UIViewAnimationOptionCurveEaseInOut = 0 << 16, // default UIViewAnimationOptionCurveEaseIn = 1 << 16, UIViewAnimationOptionCurveEaseOut = 2 << 16, UIViewAnimationOptionCurveLinear = 3 << 16, // ... }; typedef NSUInteger UIViewAnimationOptions; 

Obviamente, podría crear un método de categoría simple con una instrucción switch , así:

 // UIView+AnimationOptionsWithCurve.h @interface UIView (AnimationOptionsWithCurve) @end // UIView+AnimationOptionsWithCurve.m @implementation UIView (AnimationOptionsWithCurve) + (UIViewAnimationOptions)animationOptionsWithCurve:(UIViewAnimationCurve)curve { switch (curve) { case UIViewAnimationCurveEaseInOut: return UIViewAnimationOptionCurveEaseInOut; case UIViewAnimationCurveEaseIn: return UIViewAnimationOptionCurveEaseIn; case UIViewAnimationCurveEaseOut: return UIViewAnimationOptionCurveEaseOut; case UIViewAnimationCurveLinear: return UIViewAnimationOptionCurveLinear; } } @end 

¿Pero hay una manera aún más fácil / mejor?

Podría decirse que puede tomar su primera solución y convertirla en una function en línea para ahorrarse el impulso de stack. Es un condicional tan estricto (constante, etc.) que debería comstackrse en una pequeña pieza de ensamblaje.

Edit: Por @matt, aquí tienes (Objective-C):

 static inline UIViewAnimationOptions animationOptionsWithCurve(UIViewAnimationCurve curve) { switch (curve) { case UIViewAnimationCurveEaseInOut: return UIViewAnimationOptionCurveEaseInOut; case UIViewAnimationCurveEaseIn: return UIViewAnimationOptionCurveEaseIn; case UIViewAnimationCurveEaseOut: return UIViewAnimationOptionCurveEaseOut; case UIViewAnimationCurveLinear: return UIViewAnimationOptionCurveLinear; } } 

Swift 3:

 extension UIViewAnimationOptions { init(curve: UIViewAnimationCurve) { switch curve { case .easeIn: self = .curveEaseIn case .easeOut: self = .curveEaseOut case .easeInOut: self = .curveEaseInOut case .linear: self = .curveLinear } } } 

El método de categoría que sugiere es la forma "correcta" de hacerlo: no necesariamente tiene una garantía de que esas constantes mantengan su valor. Desde ver cómo están definidos, sin embargo, parece que podrías hacerlo

 animationOption = animationCurve << 16; 

… posiblemente con un yeso a NSUInteger y luego a UIViewAnimationOptions, si el comstackdor siente quejarse de eso.

En Swift puedes hacer

 extension UIViewAnimationCurve { func toOptions() -> UIViewAnimationOptions { return UIViewAnimationOptions(rawValue: UInt(rawValue << 16)) } } 

Un problema con la solución basada en switch es que supone que no se pasará ninguna combinación de opciones. Sin embargo, la práctica muestra que puede haber situaciones en las que la suposition no se cumple. Una instancia que encontré es (al less en iOS 7) cuando obtienes las animaciones de keyboard para animar tu contenido junto con la apariencia / desaparición del keyboard.

Si escuchas el keyboardWillShow: Will keyboardWillShow: o el keyboard Will keyboardWillHide: notifications, y luego obtienes la curva que el keyboard anuncia que usará, por ejemplo:

 UIViewAnimationCurve curve = [userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue]; 

es probable que obtenga el valor 7. Si lo pasa a la function / método de conmutación, no obtendrá una traducción correcta de ese valor, lo que dará como resultado un comportamiento de animation incorrecto.

La respuesta de Noah Witherspoon devolverá el valor correcto. Combinando las dos soluciones, puede escribir algo como:

 static inline UIViewAnimationOptions animationOptionsWithCurve(UIViewAnimationCurve curve) { UIViewAnimationOptions opt = (UIViewAnimationOptions)curve; return opt << 16; } 

La advertencia aquí, como señaló Noah también, es que si Apple cambia las enumeraciones donde los dos types ya no corresponden, entonces esta function se romperá. La razón para usarlo de todos modos, es que la opción basada en el conmutador no funciona en todas las situaciones que pueda encontrar hoy, mientras esto ocurre.