2011-09-06 40 views
41

UIKeyboardAnimationCurveUserInfoKey有一個UIViewAnimationCurve值。如何將其轉換爲相應的UIViewAnimationOptions值,供參數+[UIView animateWithDuration:delay:options:animations:completion:]使用?iOS:如何將UIViewAnimationCurve轉換爲UIViewAnimationOptions?

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

但是,有一種更簡單/更好的辦法?

回答

29

可以說,你可以把你的第一個解決方案,並使其內聯功能,以節省自己的堆棧推。它是一個非常緊湊的條件(常量限制等),它應該編譯成一個非常小的程序集。

編輯: 每@馬特,在這裏你走(的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 
     } 
    } 
} 
+0

我該怎麼做?我認爲在可能的情況下,LLVM會自動將Objective-C方法轉換爲內聯函數。 – ma11hew28

+0

聽起來像別人已經回答了你的問題:http://stackoverflow.com/questions/8194504/does-llvm-convert-objective-c-methods-to-inline-functions –

+0

我添加了內聯版本到我的答案。 –

42

你所建議的分類方法是「正確」的方法 - 你不一定有這些常數保證它們的價值。通過觀察他們是如何定義的,但是,它似乎你可以只是做

animationOption = animationCurve << 16; 

...可能帶有強制轉換爲NSUInteger再到UIViewAnimationOptions,如果編譯感覺就像抱怨說。

+8

我建議守着,隨着像'NSAssert(UIViewAnimationCurveLinear << == 16 UIViewAnimationOptionCurveLinear,@ 「意外的實施UIViewAnimationCurve的」);' – lhunath

+0

@lhunath 7用於鍵盤動畫並且是私人的。但從鍵盤傳遞userInfo。 – Andy

11

與基於交換機的解決方案的一個問題是,它不承擔任何組合的選擇將會被傳入。實踐表明,可能會出現假設不成立的情況。我發現的一個例子是(至少在iOS 7上),當您獲得鍵盤動畫以使您的內容伴隨着鍵盤的出現/消失而動起來。

如果你聽keyboardWillShow:keyboardWillHide:通知,然後拿到曲線鍵盤宣佈它將使用,如:

UIViewAnimationCurve curve = [userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue]; 

你可能如果傳遞到獲得價值7開關函數/方法,您不會得到該值的正確翻譯,導致不正確的動畫行爲。

諾亞威瑟斯龐的答案將返回正確的值。結合使用這兩種解決方案,你可能會寫類似:

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

這裏需要說明的,由諾亞還指出的是,如果蘋果發生了改變,其中兩種類型不再對應的枚舉,那麼這個功能將打破。無論如何使用它的原因是,基於開關的選項在您今天可能遇到的所有情況下都不起作用,而這樣做。

+0

如果你得到的UIKeyboardAnimationCurveUserInfoKey的值爲7,這聽起來像一個錯誤。該文檔指出該值是一個UIViewAnimationCurve。 UIViewAnimationCurve被定義爲NS_ENUM,而不是[NS_OPTIONS](http://nshipster.com/ns_enum-ns_options/)。因此,唯一可能的值是0,1,2和3.任何其他值都沒有意義。另一方面,UIViewAnimationOption被定義爲NS_OPTIONS,並且可以有大約32,000個不同的值。即使Noah的解決方案也不能處理7的值,它只會將UIViewAnimationCurveLinear傳遞給它。 – Senseful

13

在斯威夫特,你可以做

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