Core Animations 總結(jié)

前言:

Core Animation是一套包含圖形繪制、投影、動畫的Objective-C類集合,該框架包含在QuartzCore.framework中,它因為被用于處理更為強大的平滑的轉(zhuǎn)場效果而引入OS X Leopard和iOS而出名。

CPU作為電腦的處理核心,負責處理各種各樣的數(shù)據(jù),什么都可以干。而GPU作為一個專門為圖形高并發(fā)計算量身定做的處理單元,能同時更新所有的像素,并把結(jié)果顯示到顯示器上,在圖形處理方面具有相當?shù)膶I(yè)性,而且還具有高效的特點。它的出現(xiàn)使得CPU從大量的圖形數(shù)據(jù)處理中解放出來。

上圖中的OpenGL ES是個C語言寫的非常底層的圖形處理框架,是個移動設備上繪制2D和3D計算機圖形的標準開源庫,廣泛地被用在游戲的圖形繪制上,負責直接驅(qū)動GPU,效率非常高,缺點是使用起來異常復雜。

Core Animation是對OpenGL ES的Objective-C封裝,具有與OpenGL ES幾乎等價的高性能,卻隱藏了OpenGL ES的復雜性。
我們經(jīng)常說到的硬件加速其實是指OpenGL,Core Animation/UIKit基于GPU之上對計算機圖形合成以及繪制的實現(xiàn),直到目前為止,IOS上的硬件加速能力還是大大領先與Android,后者由于依賴CPU的繪制,絕大多數(shù)的動畫實現(xiàn)都會讓人感覺明顯的卡頓。

框架下各類的關系圖:

類的繼承關系

在介紹框架下各大類之前,首先需要了解一下各大圖層類的父類CALayer,也是CoreAnimation
的基礎,如果有興趣也可以看看CALayer的一些專用圖層子類。動畫是CoreAnimation
的一個顯著特性,而iOS的動畫也分顯式和隱式的。首先我們來介紹一下隱式動畫:

一、隱式動畫

當你改變CALayer的一個可做動畫的屬性,它并不能立刻在屏幕上體現(xiàn)出來。相反,它是從先前的值平滑過渡到新的值。這一切都是默認的行為,你不需要做額外的操作。

之所以叫隱式是因為我們并沒有指定任何動畫的類型。我們僅僅改變了一個屬性,然后Core Animation來決定如何并且何時去做動畫。

事務(CATransaction):

事務實際上是Core Animation用來包含一系列屬性動畫集合的機制,任何用指定事務去改變可以做動畫的圖層屬性都不會立刻發(fā)生變化,而是當事務一旦提交的時候開始用一個動畫過渡到新值。
Core Animation在每個run loop周期中自動開始一次新的事務(run loop是iOS負責收集用戶輸入,處理定時器或者網(wǎng)絡事件并且重新繪制屏幕的東西),即使你不顯式的用[CATransaction begin]開始一次事務,任何在一次run loop循環(huán)中屬性的改變都會被集中起來,然后做一次 0.25秒的動畫。core animation必須在一個transaction里執(zhí)行,在transaction里,layer tree把相應的動畫交給presentation tree去展示。

  • +begin、commit:入棧和出棧。
  • +setAnimationDuration::設置當前事務的動畫時間。
  • +animationDuration::獲取當前事務的動畫時間。
  • +setDisableActions::可以用來對所有屬性打開或關閉隱式動畫。

http://blog.csdn.net/robincui2011/article/details/9464781http://www.cnblogs.com/bandy/archive/2012/03/26/2418165.html

隱式動畫和隱式事務:

隱式動畫通過隱式事務實現(xiàn)動畫 。(除顯式事務外,任何對于CALayer屬性的修改,都是隱式事務.這樣的事務會在run-loop中被提交)

layer.backgroundColor = (layer.backgroundColor == redColor) ? blueColor : redColor;
layer.opacity = 1.0f;
layer.position = CGPointMake(layer.position.x +10, layer.position.y);

區(qū)分顯式動畫和顯式事務:

顯式動畫有多種實現(xiàn)方式,顯式事務是一種實現(xiàn)顯式動畫的方式。 ( 通過明確的調(diào)用begin,commit來提交動畫 )

通過給 CATransaction 類發(fā)送一個 begin 消息來創(chuàng)建一個顯式事務,修改完成之后發(fā)送 comit 消息。顯式事務在同時設置多個圖層的屬性的時候(例如當布局多個圖層的時候),暫時的禁用圖層的行為,或者暫時修改動畫的時間的時候非常有用 .

[CATransaction begin];
[CATransaction setValue:(_swich.on?(id)kCFBooleanTrue:(id)kCFBooleanFalse) forKey:kCATransactionDisableActions];
[self setLayerBC];
[CATransaction commit];

設置動畫是否顯示(禁用圖層行為)(方法控制區(qū)直到函數(shù)的結(jié)束):

 //默認為YES不顯示
 [CATransaction setDisableActions:NO];

暫時禁用圖層行為:
可以在修改圖層屬性值的時候通過設置事務的kCATransactionDisableActions值為 YES 來暫時禁用圖層的行為。在事務范圍所作的任何更改也不會因此而發(fā)生的動畫。

[CATransaction setValue:[NSNumber numberWithFloat:10.0f] forKey:kCATransactionAnimationDuration];

簡單使用:(如果對UIView關聯(lián)的圖層做如下動畫是沒有過渡效果的,因為UIView把它關聯(lián)的圖層的可動畫屬性關閉了)

- (IBAction)changeColor
{
    [CATransaction begin];
    [CATransaction setAnimationDuration:1.0];
    CGFloat red = arc4random() / (CGFloat)INT_MAX;
    CGFloat green = arc4random() / (CGFloat)INT_MAX;
    CGFloat blue = arc4random() / (CGFloat)INT_MAX;
    self.colorLayer.backgroundColor = [UIColor colorWithRed:red green:green blue:blue alpha:1.0].CGColor;
    //完成塊動畫,類似于UIView的completionBlock
    [CATransaction setCompletionBlock:^{
        //rotate the layer 90 degrees
        CGAffineTransform transform = self.colorLayer.affineTransform;
        transform = CGAffineTransformRotate(transform, M_PI_2);
        self.colorLayer.affineTransform = transform;
    }];
    [CATransaction commit];
}
  • UIView在+beginAnimations:context:+commitAnimations之間所有視圖或者圖層屬性的改變而做的動畫都是由于設置了CATransaction的原因。CATransaction+begin+commit方法在+animateWithDuration:animations:內(nèi)部自動調(diào)用,可以避免開發(fā)者由于對+begin+commit匹配的失誤造成的風險。

呈現(xiàn)與模型:

  • 呈現(xiàn)圖層:每個圖層屬性的顯示值都被存儲在一個叫做呈現(xiàn)圖層的獨立圖層當中,他可以通過-presentationLayer方法來訪問,可以通過呈現(xiàn)圖層的值來獲取當前屏幕上真正顯示出來的值。
  • –modelLayer:在呈現(xiàn)圖層上調(diào)用–modelLayer將會返回它正在呈現(xiàn)所依賴的CALayer。通常在一個圖層上調(diào)用-modelLayer會返回self

二、顯式動畫

能夠?qū)σ恍傩宰鲋付ǖ淖远x動畫,或者創(chuàng)建非線性動畫,比如沿著任意一條曲線移動。
使用隱式動畫會直接改變layer的屬性值,而使用顯式動畫,動畫結(jié)束時不影響動畫前的layer屬性值。
屬性動畫(CAPropertyAnimation)

內(nèi)部實現(xiàn):

CALayer的屬性被修改時候,它會調(diào)用-actionForKey:CALayer拿這個結(jié)果去對先前和當前的值做動畫。)方法,傳遞屬性的名稱。剩下的操作都在CALayer的頭文件中有詳細的說明,實質(zhì)上是如下幾步:

檢查是否有委托及委托方法是否實現(xiàn) ==>  檢查包含屬性名稱對應的action字典  ==> 在style字典里搜索屬性名  ==>   調(diào)用-defaultActionForKey:方法。
  • 圖層首先檢測它是否有委托,并且是否實現(xiàn)CALayerDelegate協(xié)議指定的-actionForLayer:forKey方法。如果有,直接調(diào)用并返回結(jié)果。
  • 如果沒有委托,或者委托沒有實現(xiàn)-actionForLayer:forKey方法,圖層接著檢查包含屬性名稱對應行為映射的actions字典。
  • 如果actions字典沒有包含對應的屬性,那么圖層接著在它的style字典接著搜索屬性名。
  • 最后,如果在style里面也找不到對應的行為,那么圖層將會直接調(diào)用定義了每個屬性的標準行為的-defaultActionForKey:方法。

當更新屬性的時候,我們需要設置一個新的事務,并且禁用圖層行為。否則動畫會發(fā)生兩次,一個是因為顯式的CABasicAnimation,另一次是因為隱式動畫

- (void)animationDidStop:(CABasicAnimation *)anim finished:(BOOL)flag
{
    [CATransaction begin];
    [CATransaction setDisableActions:YES];//禁用隱式動畫的過度效果。
    self.colorLayer.backgroundColor = (__bridge CGColorRef)anim.toValue;
    [CATransaction commit];
}
  • keyPath: CAPropertyAnimation 屬性。

基礎動畫(CABasicAnimation):

繼承自CAPropertyAnimation。參考鏈接

基礎屬性介紹:

防止動畫回到初始狀態(tài)的設置:

我們給一個視圖添加layer動畫時,真正移動并不是我們的視圖本身,而是 presentation layer (呈現(xiàn)圖層) 的一個緩存。動畫開始時 presentation layer開始移動,原始layer(model layer)隱藏,動畫結(jié)束時,presentation layer從屏幕上移除,原始layer顯示
<注>CABasicAnimation的實例對象只是一個數(shù)據(jù)模型,與綁定到哪一個layer上無關。并且用addAnimation:forKey:方法時是對CABasicAniamtion對象進行了copy操作的。

避免循環(huán)引用:

1、創(chuàng)建一個代理類實現(xiàn)其回調(diào)。

self.animation.delegate = [[AnimationDelegate alloc]init];

2、采用虛擬類NSProxy(該類可實現(xiàn)多繼承),可用YYKit中的YYWeakProxy類:

self.animation.delegate = [YYWeakProxy proxyWithTarget:self];
區(qū)分不同動畫:

此處不能使用存儲屬性作比較,因為委托傳遞的參數(shù)是對原始值的一個深拷貝,所以兩者并不是一個值。

我們在addAnimation:forKey:中可設置key值,所以可根據(jù)key值判斷:
1、對比動畫:

[anim isEqual:[self.imageView.layer animationForKey:@"Animation"]]

2、對比key:

[[anim valueForKey:@"AnimationKey"]isEqualToString:@"PositionAnima"]

組動畫 (CAAnimationGroup)

CAAnimationGroupCAAnimation的子類,可以保存一組動畫對象,將CAAnimationGroup對象加入層后,組中所有動畫對象可以同時并發(fā)運行

  • animations:用來保存一組動畫對象的NSArray默認情況下,一組動畫對象是同時運行的,也可以通過設置動畫對象的beginTime屬性來更改動畫的開始時間。
栗子:
CABasicAnimation *positionAnima = [CABasicAnimation animationWithKeyPath:@"position.y"];
positionAnima.fromValue = @(self.imageView.center.y);
positionAnima.toValue = @(self.imageView.center.y-30);
positionAnima.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];

CABasicAnimation *transformAnima = [CABasicAnimation animationWithKeyPath:@"transform.rotation.y"];
transformAnima.fromValue = @(0);
transformAnima.toValue = @(M_PI);
transformAnima.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];

CAAnimationGroup *animaGroup = [CAAnimationGroup animation];
animaGroup.duration = 2.0f;
animaGroup.fillMode = kCAFillModeForwards;
animaGroup.removedOnCompletion = NO;
animaGroup.animations = @[positionAnima,transformAnima];

[self.imageView.layer addAnimation:animaGroup forKey:@"Animation"];

關鍵幀動畫(CAKeyFrameAnimation):

相比CABasicAnimation的從fromValuetoValue的過渡動畫,CAKeyFrameAnimation可以用一個集合Values保存關鍵幀值。

  • Values:指定要用于動畫的關鍵幀值的對象數(shù)組。
  • path: 基于點的屬性的路徑。
  • keyTimesNSNumber對象的可選數(shù)組,用于定義應用給定關鍵幀段的時間,與Values數(shù)組意義對應。范圍:0~1。
  • rotationMode:設置它為常量kCAAnimationRotateAuto,圖層將會根據(jù)曲線的切線自動旋轉(zhuǎn)。
  • timingFunctionsNSArray類型,我們可以用它來對每次動畫的步驟指定不同的計時函數(shù)。但是指定函數(shù)的個數(shù)一定要等于keyframes數(shù)組的元素個數(shù)減一,因為它是描述每一幀之間動畫速度的函數(shù)。
Values方式:
CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
    animation.keyPath = @"position";

    NSValue *value1=[NSValue valueWithCGPoint:CGPointMake(100, 100)];
    NSValue *value2=[NSValue valueWithCGPoint:CGPointMake(200, 100)];
    NSValue *value3=[NSValue valueWithCGPoint:CGPointMake(200, 200)];
    NSValue *value4=[NSValue valueWithCGPoint:CGPointMake(100, 200)];
    NSValue *value5=[NSValue valueWithCGPoint:CGPointMake(100, 100)];
    animation.values=@[value1,value2,value3,value4,value5];

    animation.repeatCount=MAXFLOAT;
    animation.removedOnCompletion = NO;
    animation.fillMode = kCAFillModeForwards;
    animation.duration = 4.0f;
    animation.timingFunction=[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    animation.delegate=self;
    //指定時間點。
    animation.keyTimes = @[@(0.0),@(0.3),@(0.6),@(0.9),@(1)];
    [self.my_View.layer addAnimation:animation forKey:nil];
path方式:
CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
animation.keyPath = @"position";

CGMutablePathRef path=CGPathCreateMutable();
//繪制橢圓 橢圓距離左150,上100,橫向直徑100,豎向直徑300
CGPathAddEllipseInRect(path, NULL, CGRectMake(150, 100, 100, 300));
animation.path=path;
CGPathRelease(path);

animation.repeatCount=MAXFLOAT;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
animation.duration = 4.0f;
animation.timingFunction=[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
animation.delegate=self;
[self.my_pathView.layer addAnimation:animation forKey:nil];

過渡動畫(CATransition):

CATransition基礎

過渡動畫基礎的原則就是對原始的圖層外觀截圖,然后添加一段動畫,平滑過渡到圖層改變之后那個截圖的效果。CATransition 通常用于通過CALayer控制View子控件的過渡動畫,比如刪除控件,添加控件及切換子控件等。

CATransition有一個typesubtype來標識變換效果,type是一個NSString類型。defaultkCATransitionFade

  • type

define 定義的常量:

kCATransitionFade   交叉淡化過渡
kCATransitionMoveIn 新視圖移到舊視圖上面
kCATransitionPush   新視圖把舊視圖推出去
kCATransitionReveal 將舊視圖揭開,顯示下面的新視圖

私有方法:

cube                  立方體旋轉(zhuǎn)
suckEffect            收縮動畫
oglFlip               翻轉(zhuǎn)
rippleEffect          水波動畫
pageCurl              頁面揭開
pageUnCurl            放下頁面
cemeraIrisHollowOpen  鏡頭打開
cameraIrisHollowClose 鏡頭關閉
  • subtype
    用來控制動畫的方向:
kCATransitionFromRight
kCATransitionFromLeft
kCATransitionFromTop
kCATransitionFromBottom

對指定的圖層一次只能使用一次CATransition,因此,無論你對動畫的鍵設置什么值,過渡動畫都會對它的鍵設置成“transition”,也就是常量kCATransition。

栗子:

if (self.my_transition==nil) {
        self.my_transition=[[UIView alloc]initWithFrame:CGRectMake(0,[UIScreen mainScreen].bounds.size.height-250,[UIScreen mainScreen].bounds.size.width,250)];//這里是動畫最后的位置
        self.my_transition.backgroundColor=[UIColor redColor];
        [self.view addSubview:self.my_transition];
    }

    CATransition *animation = [CATransition animation];
    animation.duration = 1;
    animation.timingFunction = UIViewAnimationCurveEaseInOut;
    animation.fillMode = kCAFillModeForwards;
    animation.type = kCATransitionMoveIn;//
    animation.subtype = kCATransitionFromTop;//向上。
    //添加動畫
    [self.my_transition.layer addAnimation:animation forKey:nil];

CATransision可以對圖層任何變化平滑過渡的事實使得它成為那些不好做動畫的屬性圖層行為的理想候選,但是對于視圖關聯(lián)的圖層,或者是其他隱式動畫的行為,這個特性依然是被禁用的.

使用UIKit中來做動畫:
- (IBAction)switchImage
{
    [UIView transitionWithView:self.imageView duration:1.0
                       options:UIViewAnimationOptionTransitionFlipFromLeft
                    animations:^{
                        //cycle to next image
                        UIImage *currentImage = self.imageView.image;
                        NSUInteger index = [self.images indexOfObject:currentImage];
                        index = (index + 1) % [self.images count];
                        self.imageView.image = self.images[index];
                    }
                    completion:NULL];
}
在動畫過程中取消動畫:

動畫一旦被移除,圖層的外觀就立刻更新到當前的模型圖層的值。

  • 移除指定動畫:- (void)removeAnimationForKey:(NSString *)key;
  • 移除所有動畫:- (void)removeAllAnimations;

三、圖層時間

動畫的發(fā)生是需要持續(xù)一段時間的,所以計時對整個概念來說至關重要。

CAMediaTiming協(xié)議:

CAMediaTiming協(xié)議定義了在一段動畫內(nèi)用來控制逝去時間的屬性的集合,CALayerCAAnimation都實現(xiàn)了這個協(xié)議,所以時間可以被任意基于一個圖層或者一段動畫的類控制。

  • durationrepeatCount默認都是0。但這不意味著動畫時長為0秒,或者0次,這里的0僅僅代表了“默認”,也就是0.25秒和1次.

  • timeOffsettimeOffset只是讓動畫快進到某一點,例如,對于一個持續(xù)1秒的動畫來說,設置timeOffset為0.5意味著動畫將從一半的地方開始。

  • fillMode:設置當動畫開始或者動畫結(jié)束時的值。default:kCAFillModeRemoved,要把removeOnCompletion設置為NO。

全局時間:

CALayer或者CAGroupAnimation調(diào)整durationrepeatCount/repeatDuration屬性并不會影響到子動畫。但是beginTime,timeOffsetspeed屬性將會影響到子動畫。

馬赫時間:實際上是iOS和Mac OS系統(tǒng)內(nèi)核的命名,馬赫時間在設備上所有進程都是全局的--但是在不同設備上并不是全局的。當設備休眠的時候馬赫時間會暫停,也就是所有的CAAnimations(基于馬赫時間)同樣也會暫停。

CFTimeInterval time = CACurrentMediaTime();

本地時間:是根據(jù)父圖層/動畫層級關系中的beginTime,timeOffset和speed屬性計算。就和轉(zhuǎn)換不同圖層之間坐標關系一樣,CALayer同樣也提供了方法來轉(zhuǎn)換不同圖層之間的本地時間。如下:

- (CFTimeInterval)convertTime:(CFTimeInterval)t fromLayer:(CALayer *)l; 
- (CFTimeInterval)convertTime:(CFTimeInterval)t toLayer:(CALayer *)l;
暫停、快進和倒回:

給圖層添加一個CAAnimation實際上是給動畫對象做了一個不可改變的拷貝,所以對原始動畫對象屬性的改變對真實的動畫并沒有作用。相反,直接用-animationForKey:來檢索圖層正在進行的動畫可以返回正確的動畫對象,但是修改它的屬性將會拋出異常。

一個簡單的方法是可以利用CAMediaTiming來暫停圖層本身。如果把圖層的speed設置成0,它會暫停任何添加到圖層上的動畫。類似的,設置speed大于1.0將會快進,設置成一個負值將會倒回動畫。

通過增加主窗口圖層的speed,可以暫停整個應用程序的動畫。這對UI自動化提供了好處,我們可以加速所有的視圖動畫來進行自動化測試(注意對于在主窗口之外的視圖并不會被影響,比如UIAlertview)。可以在app delegate設置如下進行驗證:

self.window.layer.speed = 100;
手動動畫:

timeOffset一個很有用的功能在于你可以它可以讓你手動控制動畫進程,通過設置speed為0,可以禁用動畫的自動播放,然后來使用timeOffset來來回顯示動畫序列。這可以使得運用手勢來手動控制動畫變得很簡單。

緩沖(CAMediaTimingFunction)

動畫速度:
velocity = change / time

對于這種恒定速度的動畫我們稱之為“線性步調(diào)”.

CAMediaTimingFunction:

緩沖方程式的使用(同UIViewoptions屬性):

顯式:設置CAAnimation的timingFunctionCAMediaTimingFunction的一個對象。
隱式:可以使用CATransaction+setAnimationTimingFunction:方法。
其它:+timingFunctionWithName:,傳入以下常量。

kCAMediaTimingFunctionLinear //立即加速并且保持勻速到達終點的場景會有意義
kCAMediaTimingFunctionEaseIn //慢慢加速然后突然停止
kCAMediaTimingFunctionEaseOut  //全速開始,然后慢慢減速停止
kCAMediaTimingFunctionEaseInEaseOut //慢慢加速然后再慢慢減速
kCAMediaTimingFunctionDefault //和kCAMediaTimingFunctionEaseInEaseOut很類似,但是加速和減速的過程都稍微有些慢

隱式動畫關于緩沖方程式的使用:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    //configure the transaction
    [CATransaction begin];
    [CATransaction setAnimationDuration:1.0];
    [CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]];
    //set the position
    self.colorLayer.position = [[touches anyObject] locationInView:self.view];
    //commit transaction
    [CATransaction commit];
}
自定義緩沖函數(shù):

CAMediaTimingFunction 的構造函數(shù):+functionWithControlPoints:

  • 通過CAMediaTimingFunction-getControlPointAtIndex:values:可以用來檢索曲線的點,當知道曲線起始點和終止點,我們便可以通過這個方法將控制點找出來。

緩沖函數(shù)的介紹
Core Animation 的插值機制

value = (endValue – startValue) × time + startValue;

基于定時器的動畫

定時幀:

NSTimeriOS上的每個線程都管理了一個NSRunloop,就是通過一個循環(huán)來完成一些任務列表。
任務包括:

  • 處理觸摸事件
  • 發(fā)送和接受網(wǎng)絡數(shù)據(jù)包
  • 執(zhí)行使用gcd的代碼
  • 處理計時器行為
  • 屏幕重繪

當你設置一個NSTimer,他會被插入到當前任務列表中,然后直到指定時間過去之后才會被執(zhí)行。但是何時啟動定時器并沒有一個時間上限,而且它只會在列表中上一個任務完成之后開始執(zhí)行。這通常會導致有幾毫秒的延遲,但是如果上一個任務過了很久才完成就會導致延遲很長一段時間。

優(yōu)化

  • 我們可以用CADisplayLink讓更新頻率嚴格控制在每次屏幕刷新之后。
  • 基于真實幀的持續(xù)時間而不是假設的更新頻率來做動畫。
  • 調(diào)整動畫計時器的run loop模式,這樣就不會被別的事件干擾。

CADisplayLink:
frameInterval:整型,指定了間隔了多少幀后才執(zhí)行。(2,表示間隔2幀后執(zhí)行,也就是每秒執(zhí)行60/2 次)。

  • 優(yōu)點: 會保證幀率足夠連續(xù),使得動畫看起來更加平滑。

  • 缺點: 一些失去控制的離散的任務或者事件(例如資源緊張的后臺程序)可能會導致動畫偶爾地丟幀。丟幀后直接忽略,然后下一次更新時繼續(xù)運行。

可以同時對CADisplayLink指定多個run loop模式,于是我們可以同時加入NSDefaultRunLoopModeUITrackingRunLoopMode來保證它不會被滑動打斷,也不會被其他UIKit控件動畫影響性能,像這樣:

self.timer = [CADisplayLink displayLinkWithTarget:self selector:@selector(step:)];
[self.timer addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
[self.timer addToRunLoop:[NSRunLoop mainRunLoop] forMode:UITrackingRunLoopMode];

全文基于對iOS Core Animation譯文的理解,如果喜歡請記得關注我。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • 在iOS中隨處都可以看到絢麗的動畫效果,實現(xiàn)這些動畫的過程并不復雜,今天將帶大家一窺ios動畫全貌。在這里你可以看...
    每天刷兩次牙閱讀 8,697評論 6 30
  • 在iOS中隨處都可以看到絢麗的動畫效果,實現(xiàn)這些動畫的過程并不復雜,今天將帶大家一窺iOS動畫全貌。在這里你可以看...
    F麥子閱讀 5,271評論 5 13
  • 書寫的很好,翻譯的也棒!感謝譯者,感謝感謝! iOS-Core-Animation-Advanced-Techni...
    錢噓噓閱讀 2,441評論 0 6
  • 轉(zhuǎn)載:http://www.cnblogs.com/jingdizhiwa/p/5601240.html 1.ge...
    F麥子閱讀 1,874評論 0 1
  • 10月19日,由邵陽市婦聯(lián)主辦,邵陽市家庭教育研究會承辦的,“文明創(chuàng)建,大愛邵陽”,農(nóng)村留守兒童關愛保護活動...
    顏yxy閱讀 569評論 0 1

友情鏈接更多精彩內(nèi)容