web-dev-qa-db-ja.com

iOS:UIViewAnimationCurveをUIViewAnimationOptionsに変換する方法は?

UIKeyboardAnimationCurveUserInfoKeyにはUIViewAnimationCurve値があります。 +[UIView animateWithDuration:delay:options:animations:completion:]UIViewAnimationOptions引数で使用するために、対応する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ステートメントを使用して単純なカテゴリメソッドを作成できます。

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

しかし、もっと簡単で良い方法はありますか?

47
ma11hew28

おそらく、最初のソリューションをインライン関数にして、スタックプッシュを節約できます。これは非常にタイトな条件(定数制約など)であり、かなり小さなアセンブリにコンパイルする必要があります。

編集:@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;
  }
}

スウィフト3:

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

提案するカテゴリ方式は、それを行う「正しい」方法です。必ずしも、それらの定数が値を維持することを保証する必要はありません。しかし、それらがどのように定義されているかを見ると、あなたはただ行うことができるようです

animationOption = animationCurve << 16;

...コンパイラーが不満を感じている場合は、NSUIntegerへのキャストを使用してから、UIViewAnimationOptionsへのキャストを使用することもできます。

44

Swiftで

extension UIViewAnimationCurve {
    func toOptions() -> UIViewAnimationOptions {
        return UIViewAnimationOptions(rawValue: UInt(rawValue << 16))
    }
}
18
Tomáš Linhart

スイッチベースのソリューションの問題は、オプションの組み合わせが渡されないことを想定していることです。ただし、想定が成り立たない状況が存在する可能性があることを練習では示しています。私が見つけた1つの例は、(少なくともiOS 7では)キーボードのアニメーションを取得して、キーボードの外観/非表示とともにコンテンツをアニメーション化したときです。

keyboardWillShow:またはkeyboardWillHide:通知、次にキーボードが使用することをアナウンスするカーブを取得します。例:

UIViewAnimationCurve curve = [userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue];

値7を取得する可能性があります。それをスイッチ関数/メソッドに渡すと、その値の正しい変換が得られず、アニメーションの動作が不正確になります。

ノア・ウィザースプーンの答えは正しい値を返します。 2つのソリューションを組み合わせると、次のように記述できます。

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

ここでの警告は、Noahも述べたように、Appleが2つの型が対応しなくなった列挙を変更した場合、この関数は機能しなくなるということです。とにかくそれを使用する理由は、スイッチベースのオプションは、今日発生する可能性のあるすべての状況で機能するわけではありませんが、これは機能します。

11
Antonio Nunes