Domanda iOS: come convertire UIViewAnimationCurve in UIViewAnimationOptions?


Il UIKeyboardAnimationCurveUserInfoKey ha un UIViewAnimationCurve valore. Come lo converto al corrispondente UIViewAnimationOptions valore per l'uso con il options argomento di +[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;

Ovviamente, potrei creare un semplice metodo di categoria con a switch affermazione, in questo modo:

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

Ma c'è un modo ancora più semplice / migliore?


44
2017-09-06 23:17


origine


risposte:


Probabilmente puoi prendere la tua prima soluzione e renderla una funzione inline per risparmiare te stesso. È un condizionale talmente rigido (costante, ecc.) Che dovrebbe essere compilato in un piccolo pezzo di assemblaggio.

Modificare: Per @matt, qui vai (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
        }
    }
}

30
2017-11-16 20:53



Il metodo di categoria che suggerisci è il modo "giusto" per farlo: non è necessariamente garantito che tali costanti mantengano il loro valore. Dal vedere come sono definiti, però, sembra che tu possa semplicemente farlo

animationOption = animationCurve << 16;

... possibilmente con un cast su NSUInteger e poi su UIViewAnimationOptions, se il compilatore ha voglia di lamentarsi di ciò.


42
2017-09-06 23:39



In Swift puoi farlo

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

15
2018-03-11 10:33



Un problema con la soluzione basata su switch è che non presuppone che nessuna combinazione di opzioni possa mai essere inoltrata. La pratica mostra però che ci possono essere situazioni in cui l'assunto non è valido. Un'istanza che ho trovato è (almeno su iOS 7) quando ottieni le animazioni della tastiera per animare i tuoi contenuti insieme all'aspetto / scomparsa della tastiera.

Se ascolti il keyboardWillShow: o keyboardWillHide: notifiche, e quindi ottenere la curva la tastiera annuncia che utilizzerà, ad esempio:

UIViewAnimationCurve curve = [userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue];

è probabile che tu ottenga il valore 7. Se lo passi nella funzione / metodo dello switch, non otterrai una traduzione corretta di quel valore, risultando in un comportamento di animazione errato.

La risposta di Noah Witherspoon restituirà il valore corretto. Combinando le due soluzioni, potresti scrivere qualcosa come:

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

Il caveat qui, come notato anche da Noah, è che se Apple cambia le enumerazioni in cui i due tipi non corrispondono più, questa funzione si interromperà. La ragione per usarlo comunque è che l'opzione basata su switch non funziona in tutte le situazioni che potresti incontrare oggi, mentre ciò avviene.


11
2017-11-25 09:52