Block深入淺出 (一)

一 概述

閉包就是1個(gè)函數(shù)或指向函數(shù)的指針+該函數(shù)的執(zhí)行的上下文變量(也就是自由變量),Block是OC對(duì)于閉包的實(shí)現(xiàn)。其中Block可以定義在方法的內(nèi)部或外部,其本質(zhì)是對(duì)象,作用是使代碼高聚合,只有調(diào)用Block的時(shí)候,才會(huì)調(diào)用代碼塊里的內(nèi)容。

使用clang將OC代碼轉(zhuǎn)換為C++文件查看block的方法:

  • 在命令行輸入代碼 clang -rewrite-objc 需要編譯的OC的.m文件(如果這步報(bào)錯(cuò)找不到UIKit,就是用這個(gè)命令生成 clang -x objective-c -rewrite-objc -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk 需要編譯的OC的.m)
  • 這時(shí)查看當(dāng)前的文件夾里 多了一個(gè)相同名稱的 .cpp文件,可以在命令行輸入 open 生成的.cpp 查看文件

開發(fā)中常用typedef定義一個(gè)block
void(^myBlock)(void);
使用時(shí)直接

@property (nonatomic, copy) myBlock blk;
self.blk = ^(){
        NSLog(@"typedef定義的block");
 };

定義一個(gè)無參數(shù)無返回值的block

void(^myBlock1)(void) = ^(){
        NSLog(@"我是無參無返回值block");
 };

定義一個(gè)有參數(shù)無返回值的block

void(^myBlock2)(NSString* string) = ^(NSString* string) {
        NSLog(@"我是有參數(shù)無返回值block");
 };

定義一個(gè)有參數(shù)有返回值的block

NSString*(^myBlock3)(NSString* string) = ^(NSString* string){
        return [string stringByAppendingString:@"我是有參數(shù)有返回值的block"];
 };

二 Block與外部變量

截取局部變量的值
  • 默認(rèn)情況下,對(duì)于block外的變量引用,block是將其值復(fù)制到block內(nèi)部的結(jié)構(gòu)體中來訪問的,也就是說block的自動(dòng)變量的截取只針對(duì)block塊內(nèi)部使用的自動(dòng)變量,不使用則不截取。特別注意默認(rèn)情況下block只能訪問不能修改局部變量的值。
   int a = 10;
    void(^myBlock)(void) = ^{
        NSLog(@"a的值是%d",a);
    };
    a = 20;
    myBlock();

輸出結(jié)果為a=10,因?yàn)樵赼 = 20賦值之前,a=10的值被截取到了block內(nèi)部,a不管外部怎么變化,block內(nèi)部的a永遠(yuǎn)都為10。

使用__block修飾的外部變量

對(duì)于用__block修飾的外部變量的引用,block是復(fù)制其引用地址來實(shí)現(xiàn)訪問的,所以block內(nèi)部可以修改__block修飾的外部變量的值。

    __block int a = 10;
    void(^myBlock)(void) = ^{
        NSLog(@"a的值是%d",a);
    };
    a = 20;
    myBlock();

輸出結(jié)果為a=20
為什么__block修飾的外部變量的值就可以在block內(nèi)部修改呢?
我們使用clang 將這個(gè).m文件轉(zhuǎn)成 .cpp查看一下

__attribute__((__blocks__(byref))) __Block_byref_a_0 a = {(void*)0,(__Block_byref_a_0 *)&a, 0, sizeof(__Block_byref_a_0), 10};
    void(*myBlock)(void) = ((void (*)())&__ViewController__viewDidLoad_block_impl_0((void *)__ViewController__viewDidLoad_block_func_0, &__ViewController__viewDidLoad_block_desc_0_DATA, (__Block_byref_a_0 *)&a, 570425344));
    (a.__forwarding->a) = 20;

發(fā)現(xiàn)局部變量a變成了__Block_byref_a_0結(jié)構(gòu)體類型的自動(dòng)變量實(shí)例

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

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