IOS: Как преобразовать UIViewAnimationCurve в UIViewAnimationOptions?
UIKeyboardAnimationCurveUserInfoKey
имеет значение UIViewAnimationCurve
. Как преобразовать его в соответствующее значение UIViewAnimationOptions
для использования с аргументом options
+[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;
Очевидно, я мог бы создать простой метод категории с инструкцией switch
, например:
// 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
Но есть ли еще более простой/лучший способ?
Ответы
Ответ 1
Возможно, вы можете принять свое первое решение и сделать его встроенной функцией, чтобы сэкономить себе стек. Это такой жесткий условный (постоянный и т.д.), Который он должен скомпилировать в довольно крошечный кусок сборки.
Изменить:
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
}
}
}
Ответ 2
Метод категории, который вы предлагаете, - это "правильный" способ сделать это - у вас нет гарантии того, что эти константы сохраняют свою ценность. От взгляда на то, как они определены, однако, кажется, вы могли просто сделать
animationOption = animationCurve << 16;
... возможно, с приведением в NSUInteger, а затем в UIViewAnimationOptions, если компилятор чувствует, что жалуется на это.
Ответ 3
В Swift вы можете сделать
extension UIViewAnimationCurve {
func toOptions() -> UIViewAnimationOptions {
return UIViewAnimationOptions(rawValue: UInt(rawValue << 16))
}
}
Ответ 4
Проблема с решением на основе коммутатора заключается в том, что он не предполагает, что никакая комбинация параметров никогда не будет передаваться. Практика показывает, что могут быть ситуации, когда предположение не выполняется. Один экземпляр, который я нашел, - это (по крайней мере, на iOS 7), когда вы получаете анимацию клавиатуры для анимации вашего контента вместе с появлением/исчезновением клавиатуры.
Если вы прослушаете уведомления keyboardWillShow:
или keyboardWillHide:
, а затем получите кривую, которую объявляет клавиатура, например:
UIViewAnimationCurve curve = [userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue];
вы, вероятно, получите значение 7. Если вы передадите это в функцию/метод switch, вы не получите правильный перевод этого значения, что приведет к неправильному поведению анимации.
Ответ Ноа Уизерспуна вернет правильное значение. Объединив два решения, вы можете написать что-то вроде:
static inline UIViewAnimationOptions animationOptionsWithCurve(UIViewAnimationCurve curve)
{
UIViewAnimationOptions opt = (UIViewAnimationOptions)curve;
return opt << 16;
}
Оговорка здесь, как отметил Ной, также заключается в том, что если Apple когда-либо изменяет перечисления, где эти два типа больше не соответствуют, то эта функция будет ломаться. Причина, по которой это все равно, заключается в том, что опция на основе коммутатора не работает во всех ситуациях, с которыми вы можете столкнуться сегодня, в то время как это делает.