首页 > 其他分享 >iOS开发基础131-isa指针

iOS开发基础131-isa指针

时间:2024-07-18 11:30:16浏览次数:13  
标签:obj uintptr iOS 计数 131 引用 isa 指针

iOS中isa指针是Objective-C对象内部的一个重要概念,它是实现对象与类之间关系的核心机制。深入理解isa指针对掌握Objective-C的底层运行机制和对象模型非常重要。

1. 什么是isa指针

每个Objective-C对象都有一个isa指针,它指向这个对象所属的类。类本身也有一个isa指针,指向其元类(metaclass)。元类本身又有一个isa指针,指向根元类,通常是NSObject的元类。

isa 指针的优化:非指针 isa

在现代 64 位架构中,isa 指针被设计成一个压缩的位域结构,以便更多的编码信息可以直接存储在 isa 指针中,而不仅仅是一个指向类对象的指针。

64 位系统下 isa 的优化结构

以 Apple 的开源 Objective-C 运行时为例,在 64 位系统上,具体的位域结构如下:

union isa_t {
    isa_t() { }
    isa_t(uintptr_t value) : bits(value) { }

    Class cls;
    uintptr_t bits;
    struct {
        uintptr_t nonpointer        : 1;  // 指示是否启用了优化版 isa
        uintptr_t has_assoc         : 1;  // 是否有 associated 对象
        uintptr_t has_cxx_dtor      : 1;  // 是否有 C++ 析构函数
        uintptr_t shiftcls          : 33; // 实际的类指针
        uintptr_t magic             : 6;  // 调试时用的所谓的“魔数”
        uintptr_t weakly_referenced : 1;  // 是否被弱引用
        uintptr_t deallocating      : 1;  // 是否正在被销毁
        uintptr_t has_sidetable_rc  : 1;  // 是否拥有引用计数
        uintptr_t extra_rc          : 19; // 一部分的引用计数
    };
};

2. isa 指针的实际用途

  • 类信息存储: 通过isa指针,运行时系统可以找到对象的类,并获取类的方法列表、属性列表等。
  • 类型检查和方法调用: 运行时通过isa指针实现类型检查和方法调用机制(动态绑定)。

在运行时,isa 指针用于以下几种目的:

2.1 动态类型识别

通过 isa 指针,运行时能够识别对象的实际类型。这对于动态消息传递系统至关重要。

- (void)someMethod {
    if ([self isKindOfClass:[NSString class]]) {
        NSLog(@"This object is a NSString or subclass");
    }
}

2.2 方法分派

Objective-C 运行时通过 isa 指针找到类对象,然后在类对象的方法缓存和方法列表中搜索方法实现。这就是动态绑定的机制。

void objc_msgSend(id self, SEL _cmd, ...) {
    Class cls = object_getClass(self);
    // 查找方法实现
    IMP imp = class_getMethodImplementation(cls, _cmd);
    // 调用方法实现
    imp(self, _cmd, ...);
}

3. isa 的非指针优化和引用计数

在非指针 isa 优化下,isa 中存储了引用计数的一部分,通过以下三个字段表示:

  • extra_rc: 额外的引用计数。当引用计数超过某个范围时,将额外的计数存储在 extra_rc 中。
  • has_sidetable_rc: 当引用计数超出了 extra_rc 能表示的范围时,会使用 SideTable 来存储更多的引用计数。

简化引用计数操作的方法:

增加引用计数

void objc_retain(id obj) {
    if (obj) {
        if (!obj->isa.nonpointer) {
            // 传统方式增加引用计数
            // objc::UnretainedUnsafe<objc_object> unretainedObject(obj);
            obj->retainCount++;
        } else {
            // 使用非指针 isa 增加引用计数
            if ((obj->isa.extra_rc) < 0xFFFFFF) {
                obj->isa.extra_rc++;
            } else {
                // 使用 SideTable 计数
                // sidetable_retain(obj);
            }
        }
    }
}

减少引用计数

void objc_release(id obj) {
    if (obj) {
        if (!obj->isa.nonpointer) {
            // 传统方式减少引用计数
            // objc::UnretainedUnsafe<objc_object> unretainedObject(obj);
            obj->retainCount--;
        } else {
            // 使用非指针 isa 减少引用计数
            if (obj->isa.extra_rc > 0) {
                obj->isa.extra_rc--;
            } else {
                // 使用 SideTable 计数
                // sidetable_release(obj);
            }
        }
    }
}

4. 结合源码理解 isa 指针

类与元类结构

Objective-C 的类结构与元类结构紧密相关,每个元类的 isa 都指向根元类,而根元类的 isa 指针又指向自身。

Class myClass = [NSObject class];
Class myMetaClass = object_getClass(myClass);

// 打印类信息
NSLog(@"Class: %@, MetaClass: %@", myClass, myMetaClass);

// 检查根元类
Class rootMetaClass = object_getClass(myMetaClass);
NSLog(@"RootMetaClass: %@", rootMetaClass);

// 元类的 isa 指针会指向根元类
NSLog(@"RootMetaClass isa: %@", *(Class *)((intptr_t)rootMetaClass & ~(1ULL<<62)));

使用 lldb 调试 isa 指针

可以使用 lldb 调试器查看对象的 isa 指针和相关信息,进一步理解底层结构:

(lldb) po [myObject class]
(lldb) p/x myObject->isa

总结

isa 指针是 Objective-C 运行时的核心机制之一,通过理解其内存布局和底层实现,我们可以更深入地了解动态类型系统、方法分派机制以及引用计数优化。这些知识有助于我们编写更高效、更可靠的 Objective-C 代码,同时也为调试和性能优化提供了强有力的工具。

标签:obj,uintptr,iOS,计数,131,引用,isa,指针
From: https://www.cnblogs.com/chglog/p/18309161

相关文章

  • iOS开发基础129-音频录制上传
    在Objective-C中,音频录制过程涉及几个关键步骤,包括配置录音设置、创建和启动录音机、处理录音会话以及将录制的音频文件上传到服务器。下面是一个详细的示例,包括创建一个简单的音频录制应用,以及将录制的音频文件上传到服务器的代码。1.设置音频会话我们需要使用AVFoundation框......
  • iOS开发基础127-深入探讨KVO
    一、基础KVO(Key-ValueObserving,键值观察)是Cocoa提供的一种机制,它允许我们观察属性的变化并做出响应。这种机制非常强大,广泛应用于各种编程场景,如数据绑定、状态变化监控等。在深入了解KVO之前,我们先从KVO的基本概念开始,然后逐步探讨其深层次应用和一些使用实践的注意事项......
  • 在 PowerShell 中Get-WmiObject Win32_PhysicalMemory,SMBIOSMemoryType 是一种用于描
    在PowerShell中Get-WmiObjectWin32_PhysicalMemory,SMBIOSMemoryType是一种用于描述系统中物理内存类型的属性。数字26表示特定的内存类型,具体为DDR4内存。每种内存类型在SMBIOS(SystemManagementBIOS)规范中都有一个对应的数字码,用来标识不同类型的内存。以下是一些常见......
  • iOS开发基础125-深入探索SDWebImage
    SDWebImage是一个流行的用于处理图像下载和缓存的库,广泛用于iOS开发中,提供了一系列方便的API来下载和缓存图像,以提高应用的性能和用户体验。以下是对其进行详细介绍和分析,包括其原理和底层实现。一、SDWebImage的主要功能图像下载和缓存:图像下载:使用异步方式从网络上下......
  • iOS开发基础124-RunLoop实现卡顿检测
    利用RunLoop实现卡顿检测的基本思路是通过监听RunLoop的状态变化来判断主线程的执行时长。如果RunLoop在某个状态停留的时间超过了预设的时间阈值,则认为发生了卡顿。在具体实现中,可以利用CFRunLoopObserver来监听RunLoop的状态变化,并记录时间差。一、卡顿检测的基本原......
  • iOS开发基础122-RunLoop
    深入探讨RunLoop的底层实现需要了解CoreFoundation框架中的CFRunLoop以及与RunLoop工作机制紧密相关的操作系统底层API。这些底层实现主要涉及到事件源、定时器和线程的调度机制。本文将深入剖析RunLoop的底层结构及其运行流程。一、RunLoop底层数据结构涉及RunLo......
  • iOS开发基础123-自动释放池
    自动释放池(AutoreleasePool)是Objective-C中用于管理内存的一个重要机制,它帮助开发者简化内存管理的工作。自动释放池的核心概念是将对象放入池中,在某个时刻由系统统一释放这些对象。这种机制在iOS和macOS的应用开发中广泛使用,尤其是在事件循环和线程运行时。为了深入理解其底层......
  • vue请求接口常用写法(axios)
    1.项目根目录下新建一个utils文件夹,并新建一个request.js文件(注意:是以axios方法请求的,所以需要先安装axios或cdn引入)安装:npmnpminstallaxios-Syarnyarnaddaxios-Scdn<scriptsrc="https://unpkg.com/axios/dist/axios.min.js"></script>&&配置代码imp......
  • iOS开发基础119-组件化
    一、引言组件化是将应用程序分解成多个独立模块的设计方法,这些模块可以单独开发、测试和维护。对于大型iOS项目,组件化能够提高开发效率、降低耦合、增加代码复用性,并且使项目更易维护。本文将详细介绍如何在iOS项目中实现组件化,包括本地组件管理和远程组件管理。二、为什么......
  • iOS开发基础120-通知与线程
    NSNotificationCenter是iOS和macOS开发中用于消息传递的机制,可以在多个对象之间实现解耦的事件通知。理解NSNotificationCenter的线程模型对正确使用这一工具至关重要。NSNotificationCenter的线程模型1.消息发送线程当你通过NSNotificationCenter发送消息时,消息会......