Object-C高级编程读书笔记(2)——Block的实质

2023-10-17 19:30

本文主要是介绍Object-C高级编程读书笔记(2)——Block的实质,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

按照OC高级编程书中所说,所谓Block实质就是Object-C对象

如何理解这句话呢?应该从OC的类对象所拥有的特征入手,如果Block同样拥有这些特征,那么Block当然也就是OC的对象。

Object-C对象

在OC中,我们可以用id类型来统一代表所有的OC对象类型。那OC运行时又是如何知道id所指向的对象类型具体是那种呢?

我们知道,在OC中,基本上所有的类,最终都有一个相同的父类NSObject,查看NSObject定义,发现其只有一个Class类型的变量isa

@interface NSObject <NSObject> {Class isa  OBJC_ISA_AVAILABILITY;
}

而Class类型则为

/// An opaque type that represents an Objective-C class.
typedef struct objc_class *Class;

通过注释,可得知Class类型就是OC中的一个统一的类类型,及通过isa变量,可以区分不同对象所属的具体的类的类别。

再看objc_class 的定义

struct objc_class {Class isa  OBJC_ISA_AVAILABILITY;#if !__OBJC2__Class super_class                                        OBJC2_UNAVAILABLE;const char *name                                         OBJC2_UNAVAILABLE;long version                                             OBJC2_UNAVAILABLE;long info                                                OBJC2_UNAVAILABLE;long instance_size                                       OBJC2_UNAVAILABLE;struct objc_ivar_list *ivars                             OBJC2_UNAVAILABLE;struct objc_method_list **methodLists                    OBJC2_UNAVAILABLE;struct objc_cache *cache                                 OBJC2_UNAVAILABLE;struct objc_protocol_list *protocols                     OBJC2_UNAVAILABLE;
#endif} OBJC2_UNAVAILABLE;

其中还有个isa, 递归定义,应该是对自己的一个说明。再看其余变量,

<pre name="code" class="objc">  const char *name                                         类名称long version                                           版本long info                                              信息
 

 
long instance_size                                       对象的sizestruct objc_ivar_list *ivars                           对象变量列表struct objc_method_list **methodLists                  对象方法列表struct objc_cache *cache                               struct objc_protocol_list *protocols                   对象遵循的protocol列表

以上这些内容,也能够说明该类是个什么样子了,因此,OC对象通过继承NSObjec的Class类型的isa变量,并在isa变量中填写自身类的相关信息,OC运行时就可以通过OC对象中的isa变量,来辨别该对象属于哪个具体的类了。

那么,反过来说,如果一个对象,具有isa变量,则就可以说是OC对象了。(OC运行时通过isa来辨别该对象的具体类)。

因此,证明Block本质是一个OC对象这个问题,就转换为了Block对象是否含有isa变量这个问题。

从Block的C++代码实现看Block的本质

OC高级编程中,作者通过clang命令,将OC代码编译为C++代码,

原始OC代码

int main(){void(^blk)(void) = ^{printf("Block\n");};blk();return 0;
}

转换后的C++代码,

主要看Block类型变量,转换为了__main_block_impl_0的结构体类型,

int main(){void(*blk)(void) = (void(*)(void))&__main_block_impl_0(__main_block_func_0, __main_block_desc_0_DATA);
}

而__main_block_impl_0的结构体 定义如下

struct __main_block_imp_0{struct __block_impl imply;struct __main_block_desc_0 *Desc;// 构造函数
省略
};

可以看到结构体主要是包含一个结构体变量和一个指向结构体变量的指针,

struct __block_impl imply;
 struct __main_block_desc_0 *Desc
从名字就可以看出,imply主要涉及Block的实现相关信息,而Desc指针则是对于block的描述,这里不重要不研究它。

重点再看imply对应得struct类型__block_impl

struct __block_impl
{
void *isa;
int Flags;
int Reserved;
void *FuncPtr;
};


Flags和Reserved分别对应标记位和保留位置,我们不去管它们。

而isa的出现,则说明了Block类型对象,同样含有isa变量,即Block变量同样使用了isa变量来保存其类的信息,即是说明,Block对象,也是一种OC类对象(这点我们稍后证明)。

FuncPtr的作用很明显,就是指向了Block变量所应该执行的函数的地址,运行Block,实际上就是执行Block对象中FuncPtr函数指针所指向的函数。

总结

在这里稍稍总结一下,通过clang,我们将OC代码转换为C++代码,发现Block变量被声明为了__main_block_impl_0结构体,而该结构体包含两个类型的成员变量

struct __block_impl 与 struct __main_block_desc_0*,通过查看struct __block_impl类型,可知其中有两个较为重要的变量

void *isa(证明Block变量是OC类变量的一种), FuncPtr(Block函数实现的机制)。

下面通过代码及断点,观察blk变量的结构,确实也证明了上面的说法。

#import <Foundation/Foundation.h>int main(int argc, const char * argv[]) {@autoreleasepool {void(^blk)(void) = ^{printf("Block\n");};blk();}return 0;
}



可以看到,Block对象blk含有成员变量__isa, _FuncPtr, _flags, _reserved, __descriptor,这和我们上面关于__main_block_impl_0结构体的描述相吻合,同时可以知道,blk变量,在这里是属于__NSGlobalBlock__类的对象。

这篇关于Object-C高级编程读书笔记(2)——Block的实质的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/227475

相关文章

Apache 高级配置实战之从连接保持到日志分析的完整指南

《Apache高级配置实战之从连接保持到日志分析的完整指南》本文带你从连接保持优化开始,一路走到访问控制和日志管理,最后用AWStats来分析网站数据,对Apache配置日志分析相关知识感兴趣的朋友... 目录Apache 高级配置实战:从连接保持到日志分析的完整指南前言 一、Apache 连接保持 - 性

mysql中的group by高级用法详解

《mysql中的groupby高级用法详解》MySQL中的GROUPBY是数据聚合分析的核心功能,主要用于将结果集按指定列分组,并结合聚合函数进行统计计算,本文给大家介绍mysql中的groupby... 目录一、基本语法与核心功能二、基础用法示例1. 单列分组统计2. 多列组合分组3. 与WHERE结合使

PyTorch高级特性与性能优化方式

《PyTorch高级特性与性能优化方式》:本文主要介绍PyTorch高级特性与性能优化方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、自动化机制1.自动微分机制2.动态计算图二、性能优化1.内存管理2.GPU加速3.多GPU训练三、分布式训练1.分布式数据

Spring Boot集成SLF4j从基础到高级实践(最新推荐)

《SpringBoot集成SLF4j从基础到高级实践(最新推荐)》SLF4j(SimpleLoggingFacadeforJava)是一个日志门面(Facade),不是具体的日志实现,这篇文章主要介... 目录一、日志框架概述与SLF4j简介1.1 为什么需要日志框架1.2 主流日志框架对比1.3 SLF4

Spring Boot集成Logback终极指南之从基础到高级配置实战指南

《SpringBoot集成Logback终极指南之从基础到高级配置实战指南》Logback是一个可靠、通用且快速的Java日志框架,作为Log4j的继承者,由Log4j创始人设计,:本文主要介绍... 目录一、Logback简介与Spring Boot集成基础1.1 Logback是什么?1.2 Sprin

Python 异步编程 asyncio简介及基本用法

《Python异步编程asyncio简介及基本用法》asyncio是Python的一个库,用于编写并发代码,使用协程、任务和Futures来处理I/O密集型和高延迟操作,本文给大家介绍Python... 目录1、asyncio是什么IO密集型任务特征2、怎么用1、基本用法2、关键字 async1、async

MySQL复合查询从基础到多表关联与高级技巧全解析

《MySQL复合查询从基础到多表关联与高级技巧全解析》本文主要讲解了在MySQL中的复合查询,下面是关于本文章所需要数据的建表语句,感兴趣的朋友跟随小编一起看看吧... 目录前言:1.基本查询回顾:1.1.查询工资高于500或岗位为MANAGER的雇员,同时还要满足他们的姓名首字母为大写的J1.2.按照部门

Python中Flask模板的使用与高级技巧详解

《Python中Flask模板的使用与高级技巧详解》在Web开发中,直接将HTML代码写在Python文件中会导致诸多问题,Flask内置了Jinja2模板引擎,完美解决了这些问题,下面我们就来看看F... 目录一、模板渲染基础1.1 为什么需要模板引擎1.2 第一个模板渲染示例1.3 模板渲染原理二、模板

Java并发编程之如何优雅关闭钩子Shutdown Hook

《Java并发编程之如何优雅关闭钩子ShutdownHook》这篇文章主要为大家详细介绍了Java如何实现优雅关闭钩子ShutdownHook,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起... 目录关闭钩子简介关闭钩子应用场景数据库连接实战演示使用关闭钩子的注意事项开源框架中的关闭钩子机制1.

Spring Boot 整合 SSE的高级实践(Server-Sent Events)

《SpringBoot整合SSE的高级实践(Server-SentEvents)》SSE(Server-SentEvents)是一种基于HTTP协议的单向通信机制,允许服务器向浏览器持续发送实... 目录1、简述2、Spring Boot 中的SSE实现2.1 添加依赖2.2 实现后端接口2.3 配置超时时