iOS 开发 Objective-C

iOS 底层 day11 runtime isa详解

2020-09-02  本文已影响0人  望穿秋水小作坊

一般语言通过编译链接之后,代码的执行效果已经确定。但是 OC 可以通过 Runtime API 动态修改程序执行效果,比如让 [person run] 运行时变成 [cat eat]Runtime API 提供的接口基本是 C 语言的,源码由 C/C++/汇编 语言编写,源代码是开源的。

一、本节的主题是由浅入深,深入了解 isa

1. isa 的历史演变
2. 将 isa 之前,我们来解决一些看似无关的问题 ,下面 person对象有三个数据需要存储tallrichhandsome,思考 person对象的三个数据在内存中实际占据多大?再思考如何让 person对象的三个数据 仅占用一个字节?
#import <Foundation/Foundation.h>
@interface Person : NSObjec
@property(nonatomic, assign) BOOL tall;
@property(nonatomic, assign) BOOL rich;
@property(nonatomic, assign) BOOL handsome;
@end
3. 让 person对象的三个数据 仅占用一个字节的方案一
#import "Person.h"
// 掩码
#define SPTallMask (1<<0)
#define SPRichMask (1<<1)
#define SPHandsomeMask (1<<2)

@implementation Person
{
    char _tallRichHandsome; // 仅占用一字节
}
// tall
- (void)setTall:(BOOL)tall{
    if (tall) {
        _tallRichHandsome = _tallRichHandsome | SPTallMask;
    } else {
        _tallRichHandsome = _tallRichHandsome & (~SPTallMask);
    }
}
- (BOOL)tall{
    return !!(_tallRichHandsome & SPTallMask);
}
// rich
- (void)setRich:(BOOL)rich{
    if (rich) {
        _tallRichHandsome = _tallRichHandsome | SPRichMask;
    } else {
        _tallRichHandsome = _tallRichHandsome & (~SPRichMask);
    }
}
- (BOOL)rich{
    return !!(_tallRichHandsome & SPRichMask);
}
// handsome
- (void)setHandsome:(BOOL)handsome{
    if (handsome) {
        _tallRichHandsome = _tallRichHandsome | SPHandsomeMask;
    } else {
        _tallRichHandsome = _tallRichHandsome & (~SPHandsomeMask);
    }
}
- (BOOL)handsome{
    return !!(_tallRichHandsome & SPHandsomeMask);
}

@end
4. 让 person对象的三个数据 仅占用一个字节的方案二(优化版),使用结构体的位域实现
#import "Person.h"

@implementation Person
{
    struct {
        char tall : 1;
        char rich : 1;
        char handsome : 1;
    } _tallRichHandsome;
}
// tall
- (void)setTall:(BOOL)tall{
    _tallRichHandsome.tall = tall;
}
- (BOOL)tall{
    return !!_tallRichHandsome.tall;
}
// rich
- (void)setRich:(BOOL)rich{
    _tallRichHandsome.rich = rich;
}
- (BOOL)rich{
    return !!_tallRichHandsome.rich;
}
// handsome
- (void)setHandsome:(BOOL)handsome{
    _tallRichHandsome.handsome = handsome;
}
- (BOOL)handsome{
    return !!_tallRichHandsome.handsome;
}

@end
5. 让 person对象的三个数据 仅占用一个字节的方案 三(优化版),使用共用体+结构体的位域实现
#import "Person.h"
// 掩码
#define SPTallMask (1<<0)
#define SPRichMask (1<<1)
#define SPHandsomeMask (1<<2)

@implementation Person
{
    union {
        char bits;
        struct {
            char tall : 1;
            char rich : 1;
            char handsome : 1;
        };
    } _tallRichHandsome;
}
// tall
- (void)setTall:(BOOL)tall{
    if (tall) {
        _tallRichHandsome.bits = _tallRichHandsome.bits | SPTallMask;
    } else {
        _tallRichHandsome.bits = _tallRichHandsome.bits & (~SPTallMask);
    }
}
- (BOOL)tall{
    return !!(_tallRichHandsome.bits & SPTallMask);
}
// rich
- (void)setRich:(BOOL)rich{
    if (rich) {
        _tallRichHandsome.bits = _tallRichHandsome.bits | SPRichMask;
    } else {
        _tallRichHandsome.bits = _tallRichHandsome.bits & (~SPRichMask);
    }
}
- (BOOL)rich{
    return !!(_tallRichHandsome.bits & SPRichMask);
}
// handsome
- (void)setHandsome:(BOOL)handsome{
    if (handsome) {
        _tallRichHandsome.bits = _tallRichHandsome.bits | SPHandsomeMask;
    } else {
        _tallRichHandsome.bits = _tallRichHandsome.bits & (~SPHandsomeMask);
    }
}
- (BOOL)handsome{
    return !!(_tallRichHandsome.bits & SPHandsomeMask);
}

@end
6. 接下来我们看一下 isa 指针的具体源码,是否一下子就理解其中含义了呢?
union isa_t 
{
    Class cls;
    uintptr_t bits;

# if __arm64__
#   define ISA_MASK        0x0000000ffffffff8ULL
#   define ISA_MAGIC_MASK  0x000003f000000001ULL
#   define ISA_MAGIC_VALUE 0x000001a000000001ULL
    struct {
        uintptr_t nonpointer        : 1;
        uintptr_t has_assoc         : 1;
        uintptr_t has_cxx_dtor      : 1;
        uintptr_t shiftcls          : 33; // MACH_VM_MAX_ADDRESS 0x1000000000
        uintptr_t magic             : 6;
        uintptr_t weakly_referenced : 1;
        uintptr_t deallocating      : 1;
        uintptr_t has_sidetable_rc  : 1;
        uintptr_t extra_rc          : 19;
#       define RC_ONE   (1ULL<<45)
#       define RC_HALF  (1ULL<<18)
    };
}
7. 打印了 personClass(类对象) 和 personMetaClass(元类对象)
Demo[5657:409869] personClass : 0x100003278, personMetaClass: 0x100003250
Demo[5657:409869] objClass : 0x7fff99c5c118,objMetaClass : 0x7fff99c5c0f0
Demo[5657:409869] 常量区:0x1000032b0,堆区:0x100424b70,栈区:0x7ffeefbff55c
8. 部分 isa_t 共用体含义
上一篇下一篇

猜你喜欢

热点阅读