中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

iOS?block值捕獲與指針捕獲的方法

發布時間:2022-02-08 09:21:37 來源:億速云 閱讀:360 作者:iii 欄目:開發技術

本文小編為大家詳細介紹“iOS block值捕獲與指針捕獲的方法”,內容詳細,步驟清晰,細節處理妥當,希望這篇“iOS block值捕獲與指針捕獲的方法”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。

指針與指針變量

通俗的理解:

指針:內存地址
指針變量:存放內存地址的變量
指針變量的指針:指針變量自身的內存地址

Person *p = [Person new]

iOS?block值捕獲與指針捕獲的方法

右邊isa為:對象的內存地址 - 指針

p為:指針變量

左邊isa為:指針變量的內存地址 - 指針變量的指針

block捕獲變量方式

對局部變量捕獲有兩種形式:1、值捕獲(局部自動變量) 2、指針捕獲(局部靜態變量);全局變量無需捕獲,可直接進行訪問。

clang -rewrite-objc **.m -o **.cpp 不同場景下轉換成C++代碼結果如下(嫌代碼長不想看的直接看代碼下面的結論)

值捕獲

指針變量的捕獲

block內部用一個新的指針變量來接收原指針變量。接收后,兩個指針變量里面存儲的值都是對象的內存地址,所以也可以說是值的捕獲。

局部自動變量:

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Person *p = [Person new];
        void (^block)(void) = ^{
            NSLog(@"%@",p);
        };
        block();
    }
    return 0;
}
struct Person_IMPL {
    struct NSObject_IMPL NSObject_IVARS;
};

struct __main_block_impl_0 {
  struct __block_impl impl;
  struct __main_block_desc_0* Desc;
  Person *p;
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, Person *_p, int flags=0) : p(_p) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};

static void __main_block_func_0(struct __main_block_impl_0 *__cself) {

  Person *p = __cself->p; // bound by copy
            NSLog((NSString *)&__NSConstantStringImpl__var_folders_7w_wgxxl_655s9g6tms_7z44s6w0000gn_T_main_f76e59_mi_0,p);
}

static void __main_block_copy_0(struct __main_block_impl_0*dst, struct __main_block_impl_0*src) {_Block_object_assign((void*)&dst->p, (void*)src->p, 3/*BLOCK_FIELD_IS_OBJECT*/);}

static void __main_block_dispose_0(struct __main_block_impl_0*src) {_Block_object_dispose((void*)src->p, 3/*BLOCK_FIELD_IS_OBJECT*/);}

static struct __main_block_desc_0 {
  size_t reserved;
  size_t Block_size;
  void (*copy)(struct __main_block_impl_0*, struct __main_block_impl_0*);
  void (*dispose)(struct __main_block_impl_0*);
} 
__main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0), __main_block_copy_0, __main_block_dispose_0};

int main(int argc, const char * argv[]) {
    /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool;
        Person *p = ((Person *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("Person"), sel_registerName("new"));
        
        void (*block)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, p, 570425344));
        
        ((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);

    }
    return 0;
}

代碼分析,生成的__main_block_impl_0結構體里面創建了一個指針變量p,main函數里面的__main_block_impl_0初始化時,傳入的也是指針變量p。所以block對局部自動變量采用的捕獲方式是指針變量的捕獲,也就是值捕獲。

指針捕獲

對指針變量自身指針的捕獲

block內部用一個新的指針來接收(指向)原指針變量自身的地址。

局部靜態變量:

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        static Person *p = nil;
        p = [Person new];
        void (^block)(void) = ^{
            NSLog(@"%@",p);
        };
        block();
    }
    return 0;
}
struct Person_IMPL {
    struct NSObject_IMPL NSObject_IVARS;
};

struct __main_block_impl_0 {

  struct __block_impl impl;
  struct __main_block_desc_0* Desc;
  Person **p;
  
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, Person **_p, int flags=0) : p(_p) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};

static void __main_block_func_0(struct __main_block_impl_0 *__cself) {

  Person **p = __cself->p; // bound by copy
  NSLog((NSString *)&__NSConstantStringImpl__var_folders_7w_wgxxl_655s9g6tms_7z44s6w0000gn_T_main_bd39c2_mi_0,(*p));
}

static void __main_block_copy_0(struct __main_block_impl_0*dst, struct __main_block_impl_0*src) {_Block_object_assign((void*)&dst->p, (void*)src->p, 3/*BLOCK_FIELD_IS_OBJECT*/);}

static void __main_block_dispose_0(struct __main_block_impl_0*src) {_Block_object_dispose((void*)src->p, 3/*BLOCK_FIELD_IS_OBJECT*/);}

static struct __main_block_desc_0 {

  size_t reserved;
  size_t Block_size;
  void (*copy)(struct __main_block_impl_0*, struct __main_block_impl_0*);

  void (*dispose)(struct __main_block_impl_0*);

} __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0), __main_block_copy_0, __main_block_dispose_0};

int main(int argc, const char * argv[]) {

    /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool;

        static Person *p = __null;
        p = ((Person *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("Person"), sel_registerName("new"));

        void (*block)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, &p, 570425344));
        ((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);
    }
    return 0;
}

代碼分析,生成的__main_block_impl_0結構體里面創建了一個指針*p,main函數里面的__main_block_impl_0初始化時,傳入的是指針變量p的地址&p。所以block對局部靜態變量采用的捕獲方式是指針變量自身地址的捕獲,也就是指針捕獲。

__block修飾的變量

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        __block Person *p = [Person new];
        void (^block)(void) = ^{
            NSLog(@"%@",p);
        };
        block();
    }
    return 0;
}
struct Person_IMPL {
    struct NSObject_IMPL NSObject_IVARS;
};

struct __Block_byref_p_0 {
  void *__isa;
__Block_byref_p_0 *__forwarding;
 int __flags;
 int __size;
 void (*__Block_byref_id_object_copy)(void*, void*);
 void (*__Block_byref_id_object_dispose)(void*);
 Person *p;
};

struct __main_block_impl_0 {
  struct __block_impl impl;
  struct __main_block_desc_0* Desc;
  
  __Block_byref_p_0 *p; // by ref
  
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref_p_0 *_p, int flags=0) : p(_p->__forwarding) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};

static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
  __Block_byref_p_0 *p = __cself->p; // bound by ref
  NSLog((NSString *)&__NSConstantStringImpl__var_folders_7w_wgxxl_655s9g6tms_7z44s6w0000gn_T_main_6c171f_mi_0,(p->__forwarding->p));
}

static void __main_block_copy_0(struct __main_block_impl_0*dst, struct __main_block_impl_0*src) {_Block_object_assign((void*)&dst->p, (void*)src->p, 8/*BLOCK_FIELD_IS_BYREF*/);}

static void __main_block_dispose_0(struct __main_block_impl_0*src) {_Block_object_dispose((void*)src->p, 8/*BLOCK_FIELD_IS_BYREF*/);}

static struct __main_block_desc_0 {
  size_t reserved;
  size_t Block_size;
  void (*copy)(struct __main_block_impl_0*, struct __main_block_impl_0*);
  void (*dispose)(struct __main_block_impl_0*);
} __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0), __main_block_copy_0, __main_block_dispose_0};

int main(int argc, const char * argv[]) {

    /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool;
        __attribute__((__blocks__(byref))) __Block_byref_p_0 p = {(void*)0,(__Block_byref_p_0 *)&p, 33554432, sizeof(__Block_byref_p_0), __Block_byref_id_object_copy_131, __Block_byref_id_object_dispose_131, ((Person *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("Person"), sel_registerName("new"))};

        void (*block)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, (__Block_byref_p_0 *)&p, 570425344));

        ((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);

    }
    return 0;
}

代碼分析,使用__block修飾的指針變量p,會被轉換為__Block_byref_p_0的結構體,結構體內持有p。main函數里面初始化__main_block_impl_0時傳入的是__Block_byref_p_0的地址,訪問p時,通過__Block_byref_p_0的__forwarding指針進行訪問。其實就相當于block內部捕獲了__Block_byref_p_0的指針,通過指針去訪問__Block_byref_p_0持有的p。所以__block修飾的變量本質上也相當于是一種指針捕獲,只不過不是直接捕獲指針變量p的自身地址。

值捕獲能否重新賦值? 進行值拷貝時,block內部同名指針變量如果執行重新賦值操作,相當于使內部的指針變量指向了一個新的對象,再對此對象進行任何操作都與原指針變量指向的原對象無關,所以不能進行重新賦值。

指針捕獲能否重新賦值? block內部將block外部的指針變量的指針賦值給一個新的指針,block內部、外部的指針都指向的是同一個指針變量。如果進行賦值操作,操作的是同一個指針變量,所以可以進行重新賦值。

讀到這里,這篇“iOS block值捕獲與指針捕獲的方法”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

吉木萨尔县| 保亭| 松溪县| 通榆县| 石楼县| 武功县| 定西市| 马龙县| 长海县| 东平县| 西吉县| 泰兴市| 遂川县| 德惠市| 玉龙| 拜泉县| 铜梁县| 高平市| 北票市| 雷波县| 云龙县| 陆川县| 洛宁县| 沈阳市| 冀州市| 陕西省| 潜江市| 富阳市| 甘谷县| 竹溪县| 梨树县| 龙州县| 乌拉特前旗| 迭部县| 宝丰县| 海兴县| 郧西县| 墨脱县| 土默特左旗| 南江县| 巴林左旗|