iOS:如何将UIViewAnimationCurve转换为UIViewAnimationOptions?

UIKeyboardAnimationCurveUserInfoKey有一个UIViewAnimationCurve值。 如何将其转换为相应的UIViewAnimationOptions值,以便与+[UIView animateWithDuration:delay:options:animations:completion:]options参数一起使用。

 // 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; 

显然,我可以使用switch语句创build一个简单的类别方法,如下所示:

 // 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 

但是,有没有更简单/更好的方法?

可以说,你可以把你的第一个解决scheme,并使其内联function,以节省自己的堆栈推。 这是一个非常严格的条件(常量限制等),它应该编译成一个非常小的程序集。

编辑:Per @matt,在这里你去(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 } } } 

你所build议的分类方法是“正确”的方法 – 你不必保证这些常数保持其价值。 从看他们是如何定义的,但是,看来你可以做

 animationOption = animationCurve << 16; 

如果编译器觉得好像在抱怨那样,那么可能会用到NSUInteger和UIViewAnimationOptions。

在斯威夫特你可以做

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

基于交换机的解决scheme存在的一个问题是,它假定不会有任何选项的组合会被传入。实践表明,可能存在假设不成立的情况。 我发现的一个例子是(至less在iOS 7上)当您获得键盘animation来为您的内容制作animation以及键盘的出现/消失。

如果你听keyboardWillShow:keyboardWillHide:通知,然后得到键盘宣布它将使用的曲线,例如:

 UIViewAnimationCurve curve = [userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue]; 

您可能会获得值7.如果将其传递给开关函数/方法,则无法正确翻译该值,从而导致错误的animation行为。

诺亚威瑟斯庞的答案将返回正确的价值。 结合这两个解决scheme,你可能会写如下的东西:

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

正如挪亚指出的那样,这里的警告是,如果苹果改变了这两种types不再一致的枚举,那么这个function就会被打破。 无论如何,使用它的原因是,基于开关的选项不适用于您今天可能遇到的所有情况,而这样做。