在iOS開(kāi)發(fā)的時(shí)候单鹿,如果想給用戶界面加入一些簡(jiǎn)單的動(dòng)畫(huà),那UIView動(dòng)畫(huà)一定是很多人的首選。因?yàn)樗鼘?xiě)起來(lái)非常簡(jiǎn)潔霉旗,只需要把將要改變的property值放入U(xiǎn)IView的animation block中,比如:
[UIView animateWithDuration:5.0
animations:^{
myView.alpha = 0.5;
}];
但是我也一直疑惑,這樣的寫(xiě)法厌秒,和使用CAAnimation有什么不同呢读拆?有人說(shuō),UIView動(dòng)畫(huà)只是把Core Animation的一些操作封裝了起來(lái)鸵闪。雖然我也這么猜測(cè)檐晕,但是我打算寫(xiě)代碼驗(yàn)證一下。
根據(jù)這篇蘋(píng)果官方文檔蚌讼,我們可以得知辟灰,每一個(gè)view.layer都以該view作為其delegate,并通過(guò)詢問(wèn)view的actionForLayer:forKey:
方法來(lái)獲得自己應(yīng)該執(zhí)行的CAAction對(duì)象篡石。
所以我自定義了一個(gè)XSQView類芥喇,繼承自UIView,僅僅重寫(xiě)了其中的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對(duì)它的layer提供了什么樣的CAAction對(duì)象夏志。
用UIView動(dòng)畫(huà)改變XSQView對(duì)象的property乃坤,比如:
[UIView animateWithDuration:5.0
animations:^{
xsqView.alpha = 0.5;
}];
可以發(fā)現(xiàn),此時(shí)沟蔑,XSQView中的actionForLayer:forKey:
方法被多次調(diào)用湿诊,產(chǎn)生了這樣的輸出:
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]
的輸出。說(shuō)明對(duì)于其他的幾種key瘦材,UIView對(duì)象告訴它的layer厅须,停止對(duì)CAAction對(duì)象的搜索。而對(duì)opacity這個(gè)key食棕,UIView對(duì)象則給出了一個(gè)CABasicAnimation對(duì)象朗和。
打印這個(gè)CABasicAnimation對(duì)象的部分信息,發(fā)現(xiàn)這可能就是由UIView animation block中的代碼轉(zhuǎn)換出的CAAnimation簿晓。
<CABasicAnimation:0x7fa95275bc20; delegate = <UIViewAnimationState: 0x7fd811c376b0>; fillMode = both; timingFunction = easeInEaseOut; duration = 5; fromValue = 1; keyPath = opacity>
(但是這個(gè)CABasicAnimation中的toValue和byValue都是nil)
另外眶拉,用類似的方式觀察layer對(duì)象的行為(根據(jù)蘋(píng)果官方文檔,可以通過(guò)重載UIView中的layerClass
方法來(lái)改變這個(gè)View使用的layer的類型憔儿。所以自定義一個(gè)CALayer的子類作為view的layerClass忆植,并重寫(xiě)CALayer的部分方法起到監(jiān)控CALayer行為的目的。)谒臼,我發(fā)現(xiàn)layer的addAnimation:forKey:
方法也被調(diào)用了朝刊,這個(gè)CABasicAnimation對(duì)象被加入到了layer中。
如果在UIView的animation block中蜈缤,改變了一個(gè)view的多個(gè)property拾氓,則會(huì)有多個(gè)CAAnimation對(duì)象被加入到layer中。
我覺(jué)得到這里已經(jīng)能表明底哥,UIView動(dòng)畫(huà)其實(shí)就是對(duì)Core Animation的一種封裝咙鞍,向客戶程序員呈現(xiàn)更簡(jiǎn)潔的接口房官。
但是我也發(fā)現(xiàn)了,在UIView的animation block中改變position或者bounds等屬性续滋,會(huì)有一些特別的行為易阳。因?yàn)檫@些屬性可能對(duì)應(yīng)著多個(gè)animation key。所以吃粒,從actionForLayer:forKey:
中返回的對(duì)象也不是一個(gè)CAAnimation對(duì)象了,而是一個(gè)(沒(méi)有公開(kāi)的)_UIViewAdditiveAnimationAction
對(duì)象拒课。隨后徐勃,可能有多個(gè)CAAnimation對(duì)象被加入到layer中。