對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中。