日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Blocks编程

發布時間:2025/3/20 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Blocks编程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.介紹

Block是一個C Level的語法以及運行時的一個特性,非常像標準C中的函數(函數指針),但是其運行需要編譯器和運行時支持,目前LLVM+Clang可以很好的支持Block(蘋果修改過的GCC也可以)。Block和函數不同的是其語義?閉包?特性,以及可以有匿名block的存在。 你可以在LLVM的官方網站查看Block語言規范.?
你可以通過{}內的.

int multiplier = 2; int (^myBlock)(int) = ^(int num){ return num * multiplier; }; printf("%d",myBlock(4));

上面代碼中的 2. 聲明創建和調用

聲明Block變量?
Block變量保存著指向Block的指針,聲明一個Block變量就和聲明一個函數指針變量類似,只是將*改成了.?其他的就和C的類型系統保持一致了。

void (^blockReturningVoidWithVoidArgument)(void); int (^blockReturningIntWithIntAndCharArguments)(int, char); void (^arrayOfTenBlocksReturningVoidWithIntArgument[10])(int);

另 Block還支持可變參數variadic (...) ,沒有參數的話,變量列表的地方必須寫上void關鍵字.

聲明Block類型?你可以通過typedef聲明Block的類型,這樣多個地方需要使用同種類型的Block的時候會比較方便,

typedef float (^MyBlockType)(float, float); MyBlockType myFirstBlock = // ... ; MyBlockType mySecondBlock = // ... ;

Block創建?聲明了一個Block變量之后,可以為這個變量賦值

blockReturningVoidWithVoidArgument = ^{ printf("%s","Block Returing Void With Void Argument."); }

當然你可以在聲明變量的同時賦值

void (^blockReturningVoidWithVoidArgument)(void) = ^{ printf("%s","Block Returing Void With Void Argument."); }

Block調用?Block的調用和函數的調用是非常相似的,如上面定義的blockReturningVoidWithVoidArgument,調用的時候則直接blockReturningVoidWithVoidArgument();便可.

匿名Block?當一個Block作為函數參數的時候,一般實參都是以匿名Block的方式傳過去的。

void callVoidVoid(void (^closure)(void)) { closure(); } int main(int argc, char *argv[]) { __block int i = 10; callVoidVoid(^{ ++i; }); if (i != 11) { printf("*** %s didn't update i\n", argv[0]); return 1; } printf("%s: success\n", argv[0]); return 0; }

當然你也可以直接調用匿名Block,如

^{ ++i; }();

3.Block和變量

一個Block的內部是可以引用自身作用域外的變量的,包括static變量,extern變量或自由變量(定義一個變量的時候,如果不加存儲修飾符,默 認情況下就是自由變量auto,auto變量保存在stack中的.除了auto之外還存在register,static等存儲修飾符) ,對于自由變量,在Block中是只讀的。在引入block的同時,還引入了一種特殊的變量存儲修飾符 代碼示例 3.1

__block int blockValue = 0; int autoValue = 0; void(^printValue)(void) = ^{ printf("blockValue = %d\n",blockValue); printf("autoValue = %d\n",autoValue); }; blockValue ++; autoValue ++; printValue();

3.1中的代碼,輸出的值為

blockValue = 1 autoValue = 0

可以看到自由變量盡管自增了,但是在調用printValue這個Block的時候,看到的還是其定義的時候看到的那個autoValue的值,autoValue的值在Block的內部示無法修改的,要不然編譯器會報錯:

Semantic Issue: Variable is not assignable (missing __block type specifier)

Block定義時內存是分配在stack上的,當其作用域結束,就會被自動釋放,所以你不需要去擔心它的內存情況,我們可以對一個Block進行Block_copy()之后,Block會被拷貝到heap中的內存中,且其所有的引用到的自由變量也將會被拷貝,當然你得記得通過 在Block內部如果引用到對象或者對象的成員變量,那么當Block被拷貝 代碼示例 3.2

NSObject *testObject = [[NSObject alloc] init]; NSLog(@"%lu",[testObject retainCount]); //1 NSLog(@"%lu",[self retainCount]); //1 void(^testBlock)(void) = ^{ NSLog(@"The Test String : %@", testObject); NSLog(@"The Window Object : %@", _window); }; NSLog(@"%lu",[testObject retainCount]); //1 NSLog(@"%lu",[self retainCount]); //1 void(^testBlock2)(void) = Block_copy(testBlock); //testBlock會被拷貝到heap中,所以用完了要自己調用Block_release進行釋放 NSLog(@"%lu",[testObject retainCount]); //2 NSLog(@"%lu",[self retainCount]); //2 testBlock2(); Block_release(testBlock2); NSLog(@"%lu",[testObject retainCount]); //1 NSLog(@"%lu",[self retainCount]); //1 [testObject release];

Block的閉包特性使得Block可以脫離其定義的作用域進行運行,所以你可以在一個函數中返回一個Block,在別的線程或者當前線程的RunLoop中進行運行,而不用擔心那些引用到的外部變量是否被釋放掉了。

4.Block實際應用

那么我們一般什么時候會用到Block呢? Blocks通常是一小段自包含的代碼片段.所以它經常被用于多線程運行的代碼單元(如GCD),或用于處理聚合類元素單元,或者作為某個函數調用完成后的回調函數.

Block用作回調函數比傳統的回調函數有以下的優越性: (Jacky Shin:下面這個是重點,需要仔細理解使用場合)

  • 在函數調用的時候,將Block作為一個參數傳給函數
  • 允許訪問本地變量,這樣可以避免通過結構體將本地變量封裝后傳遞給回調函數

應用1: Animations & Completion Handler

[UIView animateWithDuration:2 animations:^{ self.view.backgroundColor = [UIColor redColor]; } completion:^(BOOL finished){ if (finished){ self.view.backgroundColor = [UIColor blueColor]; } }];

應用2: Enumeration?
對數據集合類中的每一個元素進行遍歷,每次傳入一個對象,進行處理

NSArray *cards = [NSArray arrayWithObjects:@"Jack", @"Queen", @"King", @"Ace", nil]; [cards enumerateObjectsUsingBlock:^(id object, NSUInteger index, BOOL *stop) { NSLog(@"%@ card at index %d", object, index); }];

應用3: Notification Handler

[[NSNotificationCenter defaultCenter] addObserverForName:@"TestNotification" object:nil queue:aNSOperationQueue usingBlock:^(NSNotification *notification){ NSLog(@"Notification: %@",notification); }];

應用4: GCD

dispatch_queue_t imageDownloadQueue = dispatch_queue_create("Image Download Queue", NULL); dispatch_async(imageDownloadQueue, ^{ NSURL *imageURL = [NSURL URLWithString:@"http://xxx.xx.com/a.png"]; NSData *imageData = [NSData dataWithContentsOfURL:imageURL]; UIImage *image = [UIImage imageWithData:imageData]; dispatch_async(dispatch_get_main_queue(), ^{ [imageView setImage:image]; }); });

轉載于:https://www.cnblogs.com/duyuiOS/p/4899908.html

總結

以上是生活随笔為你收集整理的Blocks编程的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。