第八課:
1、協(xié)議
另一種安全處理id類型的方式如:id <MyPRotocol> obj
a.聲明
//協(xié)議一般放于.h文件中或者在類的.h文件中@protocol Foo <Xyzzy, NSObject>//<>中的內(nèi)容表示還需實現(xiàn)自哪些協(xié)議,所有協(xié)議的根協(xié)議一般都是NSObject- (void)someMethod;//默認(rèn)為必須實現(xiàn)的方法@optional//可選方法聲明- (void)methodWithArgument:(BOOL)argument;@required@property (readonly) int readonlyProperty; //只有g(shù)etter在協(xié)議中@property NSString *readwriteProperty; //getter與setter都在協(xié)議中 - (int)methodThatReturnsSomething;@end
b.在類中實現(xiàn)協(xié)議
#import “Foo.h” @interface MyClass : NSObject <Foo> ???//(do not have to declare Foo’s methods again here, it’s implicit that you implement it)@end//或者私有實現(xiàn)@interface MyClass() <Foo>@end@implementation MyClass//@required methods here! @end
c.用途
①委托
②數(shù)據(jù)源
//UI與controller盲通信的方式@property (nonatomic, weak) id <UISomeObjectDelegate> delegate;@property (nonatomic, weak) id <UISomeObjectDataSource> dataSource;
③動畫
2、Block(來源于API文檔)
實際上為一段代碼塊,類似于C語言中的函數(shù)指針
a.聲明
int multiplier = 7;int (^myBlock)(int) = ^(int num) { return num * multiplier;};//int 為block返回值 //^表示為此為代碼塊//myBlock為此代碼塊名//int 為參數(shù)類型//等號右邊為block實現(xiàn)
block可以使用和他的同一范圍內(nèi)聲明的變量,使用block與使用C函數(shù)類似
int multiplier = 7;int (^myBlock)(int) = ^(int num) { return num * multiplier;}; printf("%d", myBlock(3));// prints "21"
b.直接使用block
block可以省略block聲明直接使用
char *myCharacters[3] = { "TomJohn", "George", "Charles Condomine" };//直接使用block作為參數(shù) qsort_b(myCharacters, 3, sizeof(char *), ^(const void *l, const void *r) { char *left = *(char **)l; char *right = *(char **)r; return strncmp(left, right, 1);}); // myCharacters is now { "Charles Condomine", "George", "TomJohn" }
c.Cocoa中使用block
NSArray *stringsArray = @[ @"string 1", @"String 21", @"string 12", @"String 11", @"String 02" ]; static NSStringCompareOptions comparisonOptions = NSCaseInsensitiveSearch | NSNumericSearch | NSWidthInsensitiveSearch | NSForcedOrderingSearch;NSLocale *currentLocale = [NSLocale currentLocale]; //比較器為代碼塊NSComparator finderSortBlock = ^(id string1, id string2) { NSRange string1Range = NSMakeRange(0, [string1 length]); return [string1 compare:string2 options:comparisonOptions range:string1Range locale:currentLocale];}; NSArray *finderSortArray = [stringsArray sortedArrayUsingComparator:finderSortBlock];NSLog(@"finderSortArray: %@", finderSortArray); /*Output:finderSortArray: ( "string 1", "String 02", "String 11", "string 12", "String 21")*/
d.__block變量
首先看簡單的例子
//直接使用變量int x = 123; void (^printXAndY)(int) = ^(int y) { printf("%d %d/n", x, y);}; printXAndY(456); // prints: 123 456//不可以直接更改變量,此處變量對block來說為只讀int x = 123;void (^printXAndY)(int) = ^(int y) { x = x + y; // error printf("%d %d/n", x, y);};
解決方法,引入__block變量
__block int x = 123; // x lives in block storage void (^printXAndY)(int) = ^(int y) { x = x + y; printf("%d %d/n", x, y);};printXAndY(456); // prints: 579 456// x is now 579
e.各種類型的變量在block中的使用
對于普通局部變量,在block聲明時保存其值,之后普通局部變量的改變對block不可見
//注意block的調(diào)用時機extern NSInteger CounterGlobal;//block對全局變量有讀寫權(quán)限static NSInteger CounterStatic;//靜態(tài)變量{ NSInteger localCounter = 42;//普通本地變量 __block char localCharacter;//__block本地變量 void (^aBlock)(void) = ^(void) { ++CounterGlobal; ++CounterStatic; CounterGlobal = localCounter; // localCounter fixed at block creation localCharacter = 'a'; // sets localCharacter in enclosing scope }; ++localCounter; // unseen by the block,對block不可見,block的值認(rèn)為42 localCharacter = 'b'; aBlock(); // execute the block // localCharacter now 'a'}
f.對象在block中的使用
dispatch_async(queue, ^{ /* block中訪問實例變量,instanceVariable為block所在類的實例變量,此時直接訪問了實例變量,因此需要對包含它的對象(self)保留 */ doSomethingWithObject(_instanceVariable);}); id localVariable = _instanceVariable;dispatch_async(queue, ^{ /* 在本地創(chuàng)建了指向?qū)嵗兞康囊茫虼诵枰A鬺ocalVariable而不是self */ doSomethingWithObject(localVariable);});
g.使用typedef聲明block
typedef float (^MyBlockType)(float, float); MyBlockType myFirstBlock = // ... ;MyBlockType mySecondBlock = // ... ;
h.Memory Cycles
//block中引用self,所以有強指針指向self,而block又在self中定義,所以self又有強指針指向block[self.myBlocks addObject:^ { [self doSomething];}];
解決方法
__weak MyClass *weakSelf = self; //重新聲明為弱引用[self.myBlocks addObject:^ { [weakSelf doSomething];}];
i.用途
枚舉,動畫,排序,通知(Notification),Error handlers,Completion handlers (錯誤與完成事件的處理,可以理解為回調(diào)函數(shù)),多線程等
3、動畫(Animation)
a.動畫的種類
Animating views :視圖動畫,包括移動、縮放、淡入淡出、旋轉(zhuǎn)等
Animation of View Controller transitions:視圖控制器動畫,視圖的切換等
Core Animation:核心動畫框架
本節(jié)課只涉及視圖動畫
b.為視圖添加動畫的三種方法
①通過設(shè)置視圖屬性
frame
transform (translation, rotation and scale)
alpha (opacity)
值會立即改變,但動畫效果會延時
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion;//適用于常規(guī)動畫設(shè)置//example[UIView animateWithDuration:3.0 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{ myView.alpha = 0.0; } completion:^(BOOL fin) { if (fin) [myView removeFromSuperview]; }];//視圖在3秒內(nèi)從父視圖淡出,完成動畫后并移除自己+ (void)transitionWithView:(UIView *)view duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion;//適用于轉(zhuǎn)場動畫設(shè)置,比如卡牌的翻轉(zhuǎn)+ (void)transitionFromView:(UIView *)fromView toView:(UIView *)toView duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options completion:(void (^)(BOOL finished))completion;//適用于切換視圖動畫
//UIViewAnimationOptions//常規(guī)動畫屬性設(shè)置(可以同時選擇多個進(jìn)行設(shè)置)UIViewAnimationOptionLayoutSubviews //父視圖變化時自動更新子視圖約束@see:http://segmentfault.com/q/1010000002872390 UIViewAnimationOptionAllowUserInteraction //動畫時響應(yīng)用戶事件,如 touch等 UIViewAnimationOptionBeginFromCurrentState //從當(dāng)前狀態(tài)開始動畫,比如此時有動畫正在改變屬性UIViewAnimationOptionRepeat //無限制重復(fù)動畫UIViewAnimationOptionAutoreverse //執(zhí)行動畫回路(動畫運行到結(jié)束點后仍然以動畫方式回到初始點),前提是設(shè)置動畫無限重復(fù)UIViewAnimationOptionOverrideInheritedDuration //忽略嵌套動畫時間設(shè)置UIViewAnimationOptionOverrideInheritedCurve //忽略嵌套動畫速度設(shè)置UIViewAnimationOptionAllowAnimatedContent //動畫過程中重繪視圖(注意僅僅適用于轉(zhuǎn)場動畫)UIViewAnimationOptionShowHideTransitionViews //視圖切換時直接隱藏舊視圖、顯示新視圖,而不是將舊視圖從父視圖移除(僅僅適用于轉(zhuǎn)場動畫)UIViewAnimationOptionOverrideInheritedOptions //不繼承父動畫設(shè)置或動畫類型//動畫速度控制(可從其中選擇一個設(shè)置)UIViewAnimationOptionCurveEaseInOut //動畫先緩慢,然后逐漸加速UIViewAnimationOptionCurveEaseIn //動畫逐漸變慢UIViewAnimationOptionCurveEaSEOut //動畫逐漸加速UIViewAnimationOptionCurveLinear //動畫勻速執(zhí)行,默認(rèn)值//轉(zhuǎn)場類型(僅適用于轉(zhuǎn)場動畫設(shè)置,可以從中選擇一個進(jìn)行設(shè)置,基本動畫、關(guān)鍵幀動畫不需要設(shè)置)UIViewAnimationOptionTransitionNone //沒有轉(zhuǎn)場動畫效果UIViewAnimationOptionTransitionFlipFromLeft //從左側(cè)翻轉(zhuǎn)效果UIViewAnimationOptionTransitionFlipFromRight //從右側(cè)翻轉(zhuǎn)效果UIViewAnimationOptionTransitionCurlUp //向后翻頁的動畫過渡效果UIViewAnimationOptionTransitionCurlDown //向前翻頁的動畫過渡效果UIViewAnimationOptionTransitionCrossDissolve //舊視圖溶解消失顯示下一個新視圖的效果UIViewAnimationOptionTransitionFlipFromTop //從上方翻轉(zhuǎn)效果UIViewAnimationOptionTransitionFlipFromBottom //從底部翻轉(zhuǎn)效果
②Dynamic Animator :動力動畫
實現(xiàn)步驟:a.創(chuàng)建一個UIDynamicAnimator
b.向UIDynamicAnimator添加UIDynamicBehaviors(gravity, collisions, etc.)
c.向UIDynamicAnimator添加UIDynamicItems(usually UIViews)
d.動畫自動運行
//Create a UIDynamicAnimatorUIDynamicAnimator *animator = [[UIDynamicAnimator alloc] initWithReferenceView:aView];//Create and add UIDynamicBehaviorsUIGravityBehavior *gravity = [[UIGravityBehavior alloc] init]; [animator addBehavior:gravity];UICollisionBehavior *collider = [[UICollisionBehavior alloc] init]; [animator addBehavior:collider];//Add UIDynamicItems to a UIDynamicBehaviorid <UIDynamicItem> item1 = ...; id <UIDynamicItem> item2 = ...; [gravity addItem:item1]; [collider addItem:item1]; [gravity addItem:item2];
//UIDynamicItem 協(xié)議@protocol UIDynamicItem@property (readonly) CGRect bounds;@property (readwrite) CGPoint center;@property (readwrite) CGAffineTransform transform; @end//一般UIView即可作為Item,天生實現(xiàn)了UIDynamic協(xié)議//以上屬性一般有動畫運行時的animator來改變,若需要主動改變,需要調(diào)用- (void)updateItemUsingCurrentState:(id <UIDynamicItem>)item;
UIDynamicBehaviors
//UIGravityBehavior@property CGFloat angle;//重力方向,默認(rèn)向下@property CGFloat magnitude; // 1.0 is 1000 points/s/s//UICollisionBehavior 碰撞@property UICollisionBehaviorMode collisionMode; // Items,Boundaries,Everything (default) - (void)addBoundaryWithIdentifier:(NSString *)identifier forPath:(UIBezierPath *)path; //用UIBezierPath自定義碰撞邊界@property BOOL translatesReferenceBoundsIntoBoundary;//參考視圖(動力動畫的頂級視圖)作為碰撞邊界//UIAttachmentBehavior 吸附行為- (instancetype)initWithItem:(id <UIDynamicItem>)item attachedToAnchor:(CGPoint)anchor;//以點作為吸附- (instancetype)initWithItem:(id <UIDynamicItem>)i1 attachedToItem:(id <UIDynamicItem>)i2;//以動力項作為吸附,兩個動力項的吸附- (instancetype)initWithItem:(id <UIDynamicItem>)item offsetFromCenter:(CGPoint)offset ... //偏移中心的吸附@property (readwrite) CGFloat length; // 吸附的長度@property (readwrite) CGPoint anchorPoint; // 吸附點@property (readwrite, nonatomic) CGFloat damping; // 錨點移動時的阻尼@property (readwrite, nonatomic) CGFloat frequency; // 錨點移動時的頻率//UISnapBehavior 捕捉行為- (instancetype)initWithItem:(id <UIDynamicItem>)item snapToPoint:(CGPoint)point; @property CGFloat damping;.//移動到錨點時振動的阻尼//UIPushBehavior 推動行為@property UIPushBehaviorMode mode; // Continuous or Instantaneous@property CGVector pushDirection;@property CGFloat magnitude/angle; // magnitude 1.0 moves a 100x100 view at 100 pts/s/s//UIDynamicItemBehavior 動力項行為,應(yīng)用于所有Items@property (readwrite, nonatomic) CGFloat elasticity; // 彈力,[0.1]@property (readwrite, nonatomic) CGFloat friction; //摩擦力,0表示無摩擦力@property (readwrite, nonatomic) CGFloat density; // 密度,默認(rèn)為1@property (readwrite, nonatomic) CGFloat resistance; //線性阻力系數(shù)0--CGFLOAT_MAX@property (readwrite, nonatomic) CGFloat angularResistance; //角度阻力系數(shù)0--CGFLOAT_MAX@property (readwrite, nonatomic) BOOL allowsRotation; //是否允許旋轉(zhuǎn)- (CGPoint)linearVelocityForItem:(id <UIDynamicItem>)item;//獲取Item速度- (CGFloat)angularVelocityForItem:(id <UIDynamicItem>)item;//獲取Item角速度
創(chuàng)建UIDynamicBehavior子類實現(xiàn)自定義行為
- (void)addChildBehavior:(UIDynamicBehavior *)behavior;//將其他行為添加到自定義行為中@property UIDynamicAnimator *dynamicAnimator;//獲取當(dāng)前行為所在的Animator- (void)willMoveToAnimator:(UIDynamicAnimator *)animator;//行為加入到方法或者移除時(此時參數(shù)為nil)會調(diào)用@property (copy) void (^action)(void);//每當(dāng)行為發(fā)生時總會執(zhí)行此block,注意調(diào)用比較頻繁的效率問題
4、demo
Dropit:https://github.com/NSLogMeng/Stanford_iOS7_Study/commit/515b76c7ed6e74a7e30108efe6d4c833f33a6e0c
課程視頻地址:網(wǎng)易公開課:http://open.163.com/movie/2014/1/D/L/M9H7S9F1H_M9H80D0DL.html
或者iTunes U搜索standford課程
新聞熱點
疑難解答