1. 程式人生 > >對UIView動畫和Core Animation的關係的一點理解

對UIView動畫和Core Animation的關係的一點理解

http://www.jianshu.com/p/72f4cca98b0e

1、UIView動畫是應用在一個view上面的,一種是使用CATransition進行更低層次的控制,UIView方式可能在低層也是使用CATransition進行了封裝。

2、CABasicAnimation動畫是應用在一個layer上面的。

在iOS開發的時候,如果想給使用者介面加入一些簡單的動畫,那UIView動畫一定是很多人的首選。因為它寫起來非常簡潔,只需要把將要改變的property值放入UIView的animation block中,比如:

[UIView animateWithDuration:5.0
animations:^{ myView.alpha = 0.5; }];

但是我也一直疑惑,這樣的寫法,和使用CAAnimation有什麼不同呢?有人說,UIView動畫只是把Core Animation的一些操作封裝了起來。雖然我也這麼猜測,但是我打算寫程式碼驗證一下。

根據這篇蘋果官方文件,我們可以得知,每一個view.layer都以該view作為其delegate,並通過詢問view的actionForLayer:forKey:方法來獲得自己應該執行的CAAction物件。

所以我自定義了一個XSQView類,繼承自UIView,僅僅重寫了其中的actionForLayer:forKey:方法:

- (id<CAAction>)actionForLayer:(CALayer *)layer forKey:(NSString *)event {
    id<CAAction> action = [super actionForLayer:layer forKey:event];
    NSLog(@"action for layer: %@, for key:%@ is %@", layer, event, action);
    return
action; }

用於觀察UIView對它的layer提供了什麼樣的CAAction物件。

用UIView動畫改變XSQView物件的property,比如:

[UIView animateWithDuration:5.0
                 animations:^{
                     xsqView.alpha = 0.5;
                 }];

可以發現,此時,XSQView中的actionForLayer:forKey:方法被多次呼叫,產生了這樣的輸出:

2015-04-06 11:59:21.373 AnimationDemo[1023:44875] action for layer: <CALayer: 0x7fa952413150>, for key:bounds is <null>
2015-04-06 11:59:21.374 AnimationDemo[1023:44875] action for layer: <CALayer: 0x7fa952413150>, for key:opaque is <null>
2015-04-06 11:59:21.375 AnimationDemo[1023:44875] action for layer: <CALayer: 0x7fa952413150>, for key:position is <null>
2015-04-06 11:59:21.375 AnimationDemo[1023:44875] action for layer: <CALayer: 0x7fa952413150>, for key:onOrderIn is <null>
2015-04-06 11:59:21.408 AnimationDemo[1023:44875] action for layer: <CALayer: 0x7fa952413150>, for key:opacity is <CABasicAnimation: 0x7fa95275bc20>

<null>[NSNull null]的輸出。說明對於其他的幾種key,UIView物件告訴它的layer,停止對CAAction物件的搜尋。而對opacity這個key,UIView物件則給出了一個CABasicAnimation物件。

列印這個CABasicAnimation物件的部分資訊,發現這可能就是由UIView animation block中的程式碼轉換出的CAAnimation。

<CABasicAnimation:0x7fa95275bc20; delegate = <UIViewAnimationState: 0x7fd811c376b0>; fillMode = both; timingFunction = easeInEaseOut; duration = 5; fromValue = 1; keyPath = opacity>

(但是這個CABasicAnimation中的toValue和byValue都是nil)

另外,用類似的方式觀察layer物件的行為(根據蘋果官方文件,可以通過過載UIView中的layerClass方法來改變這個View使用的layer的型別。所以自定義一個CALayer的子類作為view的layerClass,並重寫CALayer的部分方法起到監控CALayer行為的目的。),我發現layer的addAnimation:forKey:方法也被呼叫了,這個CABasicAnimation物件被加入到了layer中。

如果在UIView的animation block中,改變了一個view的多個property,則會有多個CAAnimation物件被加入到layer中。

我覺得到這裡已經能表明,UIView動畫其實就是對Core Animation的一種封裝,向客戶程式設計師呈現更簡潔的介面。

但是我也發現了,在UIView的animation block中改變position或者bounds等屬性,會有一些特別的行為。因為這些屬性可能對應著多個animation key。所以,從actionForLayer:forKey:中返回的物件也不是一個CAAnimation物件了,而是一個(沒有公開的)_UIViewAdditiveAnimationAction物件。隨後,可能有多個CAAnimation物件被加入到layer中。