IOS底层(十): 类相关: 成员变量与属性

2021-05-11  本文已影响0人  ShawnAlex

OC底层源码/原理合集

建议先看下
IOS底层(九): 类相关: 类结构分析
IOS底层(八): alloc相关: isa与类关联源码分析

@interface ViewController (){
    
    NSString *name ; // 成员变量, 实例变量
    int age;   // 成员变量, 基本数据类型变量
    id data;   // 成员变量, 实例变量
}

@property (nonatomic, strong) NSString *hobby;  //属性

@end

成员变量

成员变量的访问权限
@interface ViewController (){
    
    NSString * A; 
    
@public
    NSString * B;
    
@protected
    NSString * C;
    
@private
    NSString * D;
    
    @package
    NSString * E;
}

实例变量

属性 (属性变量)

@synthesize fileName, documentsDirectory

这样就可以直接访问成员属性名self->documentsDirectory


属性/成员变量本质 (底层)

首先建立一个main项目, 添加些成员变量, 属性如图(创建只有main.m项目)

属性成员变量例子

clang一下生成cpp文件

clang -rewrite-objc main.m -o main.cpp

建议先看下
IOS底层(八): alloc相关: isa与类关联源码分析 前面的Clang那里

通过我们通过TestObj查找 (因为属性/成员变量都是TestObj的), 来到这里

属性成员变量底层

① 首先可看到TestObj 来自于 NSObject的继承,
属性在底层会被编译成成员变量, 区别是带下划线 _
属性在底层会自动生成set, get方法, 而成员变量不会有

④ 同时还有我们之前得到的结论


接下来往后看

属性成员变量底层

可看到每一个方法都有一个sel, imp

iOS中提供了一个叫做@encode的指令,可以将具体的类型表示成字符串编码。

  1. @encode实际上是编译器指令其中的一种。
  2. @encode能够返回一个Objective-C 类型编码(Objective-C Type Encodings)。
  3. @encode是一种编译器内部表示的字符串,方便识别,类似于 ANSI C 的 typeof 操作。

在Objective-C中,用@encode指令的方式来表示,可以方便Runtime内部利用类型编码帮助加快消息分发。

Type Encodings 苹果官方

Property Type String 苹果官方

Type Encodings

当然我们也可以自己尝试打印一下

#pragma mark - 各种类型编码
void lgTypes(){
    NSLog(@"char --> %s",@encode(char));
    NSLog(@"int --> %s",@encode(int));
    NSLog(@"short --> %s",@encode(short));
    NSLog(@"long --> %s",@encode(long));
    NSLog(@"long long --> %s",@encode(long long));
    NSLog(@"unsigned char --> %s",@encode(unsigned char));
    NSLog(@"unsigned int --> %s",@encode(unsigned int));
    NSLog(@"unsigned short --> %s",@encode(unsigned short));
    NSLog(@"unsigned long --> %s",@encode(unsigned long long));
    NSLog(@"float --> %s",@encode(float));
    NSLog(@"bool --> %s",@encode(bool));
    NSLog(@"void --> %s",@encode(void));
    NSLog(@"char * --> %s",@encode(char *));
    NSLog(@"id --> %s",@encode(id));
    NSLog(@"Class --> %s",@encode(Class));
    NSLog(@"SEL --> %s",@encode(SEL));
    int array[] = {1,2,3};
    NSLog(@"int[] --> %s",@encode(typeof(array)));
    typedef struct person{
        char *name;
        int age;
    }Person;
    NSLog(@"struct --> %s",@encode(Person));
    
    typedef union union_type{
        char *name;
        int a;
    }Union;
    NSLog(@"union --> %s",@encode(Union));

    int a = 2;
    int *b = {&a};
    NSLog(@"int[] --> %s",@encode(typeof(b)));
}

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        lgTypes();
        NSLog(@"Hello, World!");
    }
    return 0;
}

image.png

那么以这个为例子, 我们读一下"@16@0:8"

{(struct objc_selector *)"nickname", "@16@0:8", (void *)_I_TestObj_nickname}

static NSString * _I_TestObj_nickname(TestObj * self, SEL _cmd) { return (*(NSString **)((char *)self + OBJC_IVAR_$_TestObj$_nickname)); }

clang编译输出了属性的attribute ,同样也可以通过property_getAttributes方法读取

property type string attribute

例如读取下{{"name","T@\"NSString\",C,N,V_name"},

上一篇下一篇

猜你喜欢

热点阅读