返回顶部
首页 > 资讯 > 精选 >iOS block值捕获与指针捕获的方法
  • 333
分享到

iOS block值捕获与指针捕获的方法

2023-06-29 02:06:27 333人浏览 薄情痞子
摘要

本文小编为大家详细介绍“iOS block值捕获与指针捕获的方法”,内容详细,步骤清晰,细节处理妥当,希望这篇“ioS block值捕获与指针捕获的方法”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知

本文小编为大家详细介绍“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);}static void __main_block_dispose_0(struct __main_block_impl_0*src) {_Block_object_dispose((void*)src->p, 3);}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[]) {     { __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);}static void __main_block_dispose_0(struct __main_block_impl_0*src) {_Block_object_dispose((void*)src->p, 3);}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[]) {     { __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);}static void __main_block_dispose_0(struct __main_block_impl_0*src) {_Block_object_dispose((void*)src->p, 8);}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[]) {     { __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值捕获与指针捕获的方法”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注编程网精选频道。

--结束END--

本文标题: iOS block值捕获与指针捕获的方法

本文链接: https://lsjlt.com/news/321996.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • iOS block值捕获与指针捕获的方法
    本文小编为大家详细介绍“iOS block值捕获与指针捕获的方法”,内容详细,步骤清晰,细节处理妥当,希望这篇“iOS block值捕获与指针捕获的方法”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知...
    99+
    2023-06-29
  • iOS block的值捕获与指针捕获详解
    目录指针与指针变量block捕获变量方式值捕获指针捕获__block修饰的变量关于block延伸的知识点总结指针与指针变量 通俗的理解: 指针:内存地址指针变量:存放内存地址的变量指...
    99+
    2024-04-02
  • java空指针异常如何捕获
    在Java中,可以使用try-catch语句块来捕获空指针异常(NullPointerException)。以下是一个简单的例子: ...
    99+
    2024-02-29
    java
  • java捕获空指针并处理的方法是什么
    在Java中,可以使用try-catch语句来捕获空指针异常并进行处理。具体的方法如下:1. 使用try-catch语句块捕获空指针...
    99+
    2023-08-21
    java
  • 详解ObjectiveC中Block如何捕获外部值
    目录引言自动变量静态变量、静态全局变量与全局变量带 __block 的自动变量捕获对象__block 对象类型的捕获引言 Block 本质上也是一个 Objective-C 对象,它...
    99+
    2024-04-02
  • iOS webview捕获H5按钮方法示例代码
    前言 本文主要给大家介绍了关于iOS webview捕获H5按钮的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧 方法如下: 实现iOS webview捕获...
    99+
    2022-05-29
    ios webview h5
  • php curl 错误捕获的方法
    本文操作环境:Windows7系统、PHP7.1版、DELL G3电脑php curl 错误捕获的方法curl_error($ch) 用 curl_error 来获取 curl 的错误介绍:curl_error — 返回一个保护当前会话最近...
    99+
    2016-01-18
    php curl
  • java异常级别与捕获的实现方法
    本篇内容主要讲解“java异常级别与捕获的实现方法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“java异常级别与捕获的实现方法”吧!这个是jdk 1.8文档中异常的种族描述可以看出Java异常...
    99+
    2023-06-20
  • python捕获警告的三种方法
    目录1. 警告不是异常2. 警告能捕获吗3. 捕获警告方法一4. 捕获警告方法二5. 捕获警告方法三1. 警告不是异常 你是不是经常在使用一些系统库或者第三方模块的时候,会出现一些...
    99+
    2024-04-02
  • Android崩溃异常捕获方法
    开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩...
    99+
    2022-06-06
    异常 方法 捕获 Android
  • Python使用迭代器捕获Generator返回值的方法
    本文实例讲述了Python使用迭代器捕获Generator返回值的方法。分享给大家供大家参考,具体如下: 用for循环调用generator时,发现拿不到generator的return语句的返回值。如果想...
    99+
    2022-06-04
    返回值 迭代 方法
  • Python中异常捕获与处理的方法总结
    Python异常是在程序执行时发生的错误,可能会导致程序终止运行。 在Python中,异常处理是一种机制,它允许开发人员在程序发生异常时捕获、处理和报告这些异常,以便程序可以继续运行...
    99+
    2023-05-18
    Python异常捕获 Python异常处理 Python异常
  • python捕获警告的方法有哪些
    本篇内容主要讲解“python捕获警告的方法有哪些”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“python捕获警告的方法有哪些”吧!1. 警告不是异常你是不是经常在使用一些系统库或者第三方模块...
    99+
    2023-06-14
  • c++捕获异常的方法是什么
    在C++中,可以使用try-catch块来捕获异常。试图在try块中执行代码,如果发生异常,则会立即跳转到与异常类型匹配的catch...
    99+
    2023-09-14
    c++
  • Node端异常捕获的实现方法
    目录常见Node报错处理机制try catchNode原生错误处理机制Promiseasync/await + try catchunhandledRejection特殊情况如何捕获...
    99+
    2024-04-02
  • python捕获异常的方法有哪些
    在Python中,有以下几种方法可以捕获异常:1. try-except语句:使用try-except语句块可以捕获异常。在try块...
    99+
    2023-08-08
    python
  • linux捕获信号的方法是什么
    在Linux中,捕获信号的方法有两种:1. 使用信号处理函数:可以通过使用signal()函数来注册信号处理函数,该函数的原型如下:...
    99+
    2023-08-12
    linux
  • python捕获异常的方法是什么
    在Python中,可以使用try-except语句来捕获异常。 语法如下: try: # 可能会产生异常的代码块 excep...
    99+
    2023-10-26
    python
  • python中异常捕获方法详解
    在Python中处理异常使用的是try-except代码块,try-except代码块放入让python执行的操作,同时告诉python程序如果发生了异常该怎么办,try-except这个功能其实很多入门书...
    99+
    2022-06-04
    详解 异常 方法
  • javascript捕获异常有哪些方法
    这篇文章主要介绍“javascript捕获异常有哪些方法”,在日常操作中,相信很多人在javascript捕获异常有哪些方法问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”ja...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作