2011-09-06 37 views
41

Giá trị UIKeyboardAnimationCurveUserInfoKey có giá trị UIViewAnimationCurve. Làm cách nào để chuyển đổi giá trị này thành giá trị UIViewAnimationOptions tương ứng để sử dụng với đối số options của +[UIView animateWithDuration:delay:options:animations:completion:]?iOS: Cách chuyển đổi UIViewAnimationCurve thành 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; 

Rõ ràng, tôi có thể tạo ra một phương pháp loại đơn giản với một tuyên bố switch, như vậy:

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

Nhưng, có một/cách tốt hơn thậm chí dễ dàng hơn?

Trả lời

29

Có thể cho rằng bạn có thể thực hiện giải pháp đầu tiên của mình và biến nó trở thành một hàm nội tuyến để tiết kiệm cho mình sự thúc đẩy ngăn xếp. Đó là một điều kiện chặt chẽ (liên tục ràng buộc, vv) mà nó nên biên dịch thành một mảnh khá nhỏ của hội đồng.

Edit: mỗi @ Matt, here you go (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 
     } 
    } 
} 
+0

Tôi làm như thế nào? Tôi nghĩ LLVM sẽ tự động chuyển đổi các phương thức Objective-C thành các hàm nội tuyến khi có thể. – ma11hew28

+0

Có vẻ như ai đó đã trả lời câu hỏi của bạn: http://stackoverflow.com/questions/8194504/does-llvm-convert-objective-c-methods-to-inline-functions –

+0

Tôi đã thêm phiên bản nội tuyến vào câu trả lời của mình. –

42

Phương pháp danh mục bạn đề xuất là cách "đúng" để thực hiện — bạn không nhất thiết phải đảm bảo các hằng số đó giữ giá trị của chúng. Từ nhìn vào cách chúng được xác định, tuy nhiên, có vẻ như bạn chỉ có thể làm

animationOption = animationCurve << 16; 

... có thể với một dàn diễn viên để NSUInteger và sau đó đến UIViewAnimationOptions, nếu trình biên dịch cảm thấy như phàn nàn về điều đó.

+8

Tôi khuyên bạn nên bảo vệ điều đó với một cái gì đó như 'NSAssert (UIViewAnimationCurveLinear << 16 == UIViewAnimationOptionCurveLinear, @ "thực hiện bất ngờ của UIViewAnimationCurve");' – lhunath

+0

@lhunath 7 được sử dụng cho hoạt ảnh bàn phím và riêng tư. Nhưng được chuyển với userInfo từ bàn phím. – Andy

11

Một vấn đề với giải pháp chuyển đổi dựa là nó không chịu bất cứ sự kết hợp Tùy chọn thực tế cho thấy, có thể có những tình huống mà giả định không giữ. Một ví dụ tôi tìm thấy là (ít nhất là trên iOS 7) khi bạn có được hình ảnh động bàn phím để tạo hiệu ứng nội dung của bạn cùng với sự xuất hiện/biến mất của bàn phím.

Nếu bạn lắng nghe những keyboardWillShow: hoặc keyboardWillHide: thông báo, và sau đó nhận được những đường cong như bàn phím thông báo nó sẽ sử dụng, ví dụ:

UIViewAnimationCurve curve = [userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue]; 

bạn đang có khả năng để có được những giá trị 7. Nếu bạn vượt qua đó vào chức năng chuyển đổi/phương pháp, bạn sẽ không nhận được bản dịch chính xác của giá trị đó, dẫn đến hành vi hoạt ảnh không chính xác.

Câu trả lời của Noah Witherspoon sẽ trả lại giá trị chính xác. Kết hợp hai giải pháp, bạn có thể viết một cái gì đó như:

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

Thông báo trước đây, như ghi nhận của Noah cũng có, là rằng nếu Apple bao giờ thay đổi kiểu liệt kê nơi hai loại không còn tương ứng, sau đó chức năng này sẽ phá vỡ. Lý do để sử dụng nó anyway, là tùy chọn chuyển đổi dựa trên không hoạt động trong tất cả các tình huống bạn có thể gặp phải ngày hôm nay, trong khi điều này không.

+0

Nếu bạn nhận được giá trị 7 cho UIKeyboardAnimationCurveUserInfoKey, điều đó nghe có vẻ giống như một lỗi. Tài liệu nói rằng giá trị là UIViewAnimationCurve. UIViewAnimationCurve được định nghĩa là NS_ENUM, chứ không phải [NS_OPTIONS] (http://nshipster.com/ns_enum-ns_options/). Do đó, các giá trị duy nhất có thể là 0, 1, 2 và 3. Bất kỳ giá trị nào khác là vô nghĩa. Mặt khác, UIViewAnimationOption được định nghĩa là NS_OPTIONS và có thể có khoảng 32.000 giá trị khác nhau. Thậm chí không giải pháp của Noah có thể xử lý một giá trị của 7, nó sẽ chỉ đơn giản là đối xử với nó như là mặc dù UIViewAnimationCurveLinear đã được thông qua trong. – Senseful

13

Trong Swift bạn có thể làm

extension UIViewAnimationCurve { 
    func toOptions() -> UIViewAnimationOptions { 
     return UIViewAnimationOptions(rawValue: UInt(rawValue << 16)) 
    } 
} 
Các vấn đề liên quan