白話一點Block就是一個區間(封閉的), 在程式中可以把他當作是一個function(method)既然是function的話為什麼還要特別介紹, 因為
接下來就直接看看程式碼
//sample1 [UIView animateWithDuration:2.0 animations: ^ { self.view.alpha = 1.0; self.view.frame = CGRectMake(176.0, 258.0, 72.0, 96.0); self.view.transform = CGAffineTransformMakeRotation(M_PI); } ]; //sample2 NSArray *cards = [NSArray arrayWithObjects:@"Jack", @"Queen", @"King", @"Ace", nil]; [cards enumerateObjectsUsingBlock: ^(id object, NSUInteger index, BOOL *stop) { NSLog(@"%@ card at index %d", object, index); } ]; //end上面兩個範例highlight的部分, 就是Block, 如果有注意到的話, 應該會知道這兩個Block不同的地方在於一個有待參數, 一個沒有參數(下方highlight部分)
//block1 ^ { //statement ... } //block2 ^(id object, NSUInteger index, BOOL *stop) { //statement ... }從上面, 可以知道block是可以有待參數跟沒有參數, 接著我們更進一步的介紹Block的
void (^BlockName) (void) 傳回型別 Block的名稱 參數 BlockName(); 使用上面的code, 我們可以把block分成三個部分,分別是 傳回型別(return type)、BlockName跟帶入的參數(parameters), 其中參數如果是void, 在宣告block的時候可以直接把引入的參數省略, 下面就來宣告幾個Block並使用
//sample1 void (^myName)(void) = ^ { NSLog(@"Green"); }; myName(); //sample2 int (^getAge)(void) = ^ { return 26; }; int myAge = getAge(); //sample3 NSString* (^getBirthday)(int) = ^(int mode) { NSString* birthday; switch(mode) { case 0: birthday = @"75.1.15"; break; default: birthday = @"1986.1.15"; } return birthday; }; NSString* myBirthday = getBirthday(1);看完前面有一些了解過後,我們再拿UIView有使用Block的Method來相互對照一下
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations在第二行的地方, 並沒有像前面說的有一個Block's Name, 照邊我個人理解是因為他的Block是直接使用, 所以就直接用^(cross)符號來代表匿名的block;
//sample1 void (^animation)(void) = ^{ self.view.alpha = 1.0; self.view.frame = CGRectMake(176.0, 258.0, 72.0, 96.0); self.view.transform = CGAffineTransformMakeRotation(M_PI); } [UIView animateWithDuration:2.0 animations:animation ]; //sample2 [UIView animateWithDuration:2.0 animations: ^ { self.view.alpha = 1.0; self.view.frame = CGRectMake(176.0, 258.0, 72.0, 96.0); self.view.transform = CGAffineTransformMakeRotation(M_PI); } ];sample1是用先宣告一個跟UIView ClassMethod 需要的Block Method 一樣的Block animation, 然後在呼叫UIView ClassMethod 並將 block animation 指定過去; 更快直接的話可以像sample2一樣直接打一段匿名的block, 也是可以順利執行的.
接著再來介紹 __block 這個關鍵字, 這個關鍵字是讓在block method外宣告的變數在block method可以當成變數來使用, 前面有提到說Block本身是一個封閉區間, 所以在宣告Block method本身的時候, 他會將block外部的變數當作常數來使用, 所以需要在Block變更Block外部的變數, 只要在宣告的變數前面加上__block就可以了
__block int count = 0; void(^increase)(void)=^ { count++; NSLog(@"count:%d", count); }; increase();// 1 increase();// 2 ...當我們在coding的時候, 如果有一個mehtod像上面的UIView的ClassMethod用到了Block, 但是如果要帶入的參數很多, 那在閱讀的時候會因為太長就會比較不方便, 我們可用typedef來解決這個問題
下面我建立了一個sampleMethod並要帶入一個block, 接著我們使用typedef來定義type SampleBlock, 接著把method改寫成第6行的樣子; 最下面就是一些簡單的use sample code
//before -(void)sampleMehtod:(void(^)(void))aBlock; //after typedef void(^SampleBlock)(void); -(void)sampleMethod:(SampleBlock)aBlock; //use SampleBlock testBlock = ^ { //statement ... }; [self sampleMethod:testBlock];
到這邊就告一段落啦, 因為打著Memo的口號, 我是用我自己理解的方式來寫可能只有我自己看得比較懂啦
如果有錯誤也請提出, 感謝
沒有留言:
張貼留言