007--iOS底层 - 类的结构(属性的赋值取值)

2021-06-30  本文已影响0人  Mr_wick

引言

上篇文章,通过lldb调试,找到了类的属性、成员变量、实例方法和类方法的存放位置。本文将讲述属性的补充内容。
demo

firstSubclass

上次我们在lldb调试过程中,发现这个firstSubclass都是为nil的情况,接下来,我们将讲述为什么。
上代码(QLDog继承于QLPerson):

@interface QLDog : QLPerson

@end

main.m文件
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        QLPerson *person = [QLPerson alloc];
        
        NSLog(@"%@",person);

    }
    return 0;
}

操作过程如下:

image.png
根据上图操作流程,我们可以看到,firstSubclass开始为nil,打印了QLDog地址后,firstSubclass才有值,为什么会这样呢?
因为这是一个懒加载的过程,在用到的时候才有值

属性的赋值

此处我们通过clang来探索属性的修饰对属性赋值的影响。
上代码:
QLPerson.h

@interface QLPerson : NSObject{
    NSString *fullName;
}

@property (nonatomic,copy) NSString *nickName;
@property (nonatomic,strong) NSString *strongNickName;
@property (nonatomic) NSString *noaNickName;
@property (atomic) NSString *aNickName;

@property (nonatomic,assign) NSInteger age;
@property (nonatomic) NSInteger noaAge;
@property (atomic) NSInteger aAge;


@end

通过clangQLPerson.m编译成QLPerson.cpp,请参考我之前这篇文章OC代码转C/CPP代码

xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc QLPerson.m -o QLPerson.cpp

得到的QLPerson.cpp拖入工程,不参与编译。在搜索框输入QLPerson_IMPL得到

image.png image.png

1、声明的属性,都被被注释,取而代之的是,将属性转成了成员变量+getter setter 方法
2、原成员变量fullName不变
3、方法test1 test2变成了_I_QLPerson_test1(QLPerson * self, SEL _cmd),括号内参数即可看出OC的方法调用会默认传id self,SEL _cmd两个参数。

property的getter setter方法

由上图,我们可以看到所有属性的getter和setter方法,有些不一样,代码看起来有些乱,我将多余的类型强转去掉后,简化后代码如下:

image.png
1、属性通过getter方法得到数据,方法内通过对象地址+偏移量指向的内存得到。
2、属性的赋值分两种:①setProperty()、②对象地址+偏移量
3、对比QLPerson.h中的属性声明,nickName的赋值是setProperty(),其余均为self + 偏移量。因为nickName用了copy修饰。相关证明及其setter方法重定向到setproperty()的过程,请到LLVM源码中查看。最终在CGObjC.cpp的第858行得到 image.png

总结

setProperty()objc中的运行过程,以后有空再补充。

上一篇 下一篇

猜你喜欢

热点阅读