UIKeyboardAnimationCurveUserInfoKey
a une valeur UIViewAnimationCurve
. Comment le convertir en valeur UIViewAnimationOptions
correspondante à utiliser avec l'argument 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;
Évidemment, je pourrais créer une méthode de catégorie simple avec une instruction switch
, comme ceci:
// 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
Mais, existe-t-il un moyen encore plus facile/meilleur?
On peut soutenir que vous pouvez prendre votre première solution et en faire une fonction en ligne pour vous sauver la pile Push. C'est une condition tellement stricte (à constante constante, etc.) qu'elle devrait être compilée en un assez petit morceau d'assemblage.
Edit: Par @matt, c'est parti (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
}
}
}
La méthode de catégorie que vous suggérez est la "bonne" façon de procéder: vous n'avez pas nécessairement la garantie que ces constantes conservent leur valeur. En regardant comment ils sont définis, cependant, il semble que vous pourriez simplement faire
animationOption = animationCurve << 16;
... éventuellement avec un transtypage en NSUInteger puis en UIViewAnimationOptions, si le compilateur a envie de s'en plaindre.
Dans Swift vous pouvez faire
extension UIViewAnimationCurve {
func toOptions() -> UIViewAnimationOptions {
return UIViewAnimationOptions(rawValue: UInt(rawValue << 16))
}
}
Un problème avec la solution basée sur le commutateur est qu'elle suppose qu'aucune combinaison d'options ne sera jamais transmise. La pratique montre cependant qu'il peut y avoir des situations où l'hypothèse ne tient pas. Un exemple que j'ai trouvé est (au moins sur iOS 7) lorsque vous obtenez les animations du clavier pour animer votre contenu ainsi que l'apparence/la disparition du clavier.
Si vous écoutez le keyboardWillShow:
ou keyboardWillHide:
notifications, puis obtenez la courbe que le clavier annonce qu'il utilisera, par exemple:
UIViewAnimationCurve curve = [userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue];
vous obtiendrez probablement la valeur 7. Si vous la transmettez à la fonction/méthode de commutation, vous n'obtiendrez pas une traduction correcte de cette valeur, ce qui entraînera un comportement d'animation incorrect.
La réponse de Noah Witherspoon renverra la valeur correcte. En combinant les deux solutions, vous pourriez écrire quelque chose comme:
static inline UIViewAnimationOptions animationOptionsWithCurve(UIViewAnimationCurve curve)
{
UIViewAnimationOptions opt = (UIViewAnimationOptions)curve;
return opt << 16;
}
La mise en garde ici, comme l'a également noté Noah, est que si Apple modifie jamais les énumérations où les deux types ne correspondent plus, alors cette fonction se cassera. La raison de l'utiliser de toute façon, c'est que L'option basée sur le commutateur ne fonctionne pas dans toutes les situations que vous pouvez rencontrer aujourd'hui, alors que cela fonctionne.