Objective-C运行时的一些黑魔法-成员变量与属性

文章地址

笔记:

类型编码(Type Encoding)


作为对Runtime的补充,编译器将每个方法的返回值和参数类型编码为一个字符串,并将其与方法的selector关联在一起。这种编码方案在其它情况下也是非常有用的,因此我们可以使用@encode编译器指令来获取它。当给定一个类型时,@encode返回这个类型的字符串编码。这些类型可以是诸如int、指针这样的基本类型,也可以是结构体、类等类型。事实上,任何可以作为sizeof()操作参数的类型都可以用于@encode()。

EXAMPLE:


1
2
float a[] = {1.0, 2.0, 3.0}; 
NSLog(@"array encoding type: %s", @encode(typeof(a)));

成员变量、属性

  • Ivar
    Ivar是表示实例变量的类型,其实际是一个指向objc_ivar结构体的指针。
  • objc_property_t
    objc_property_t是表示Objective-C声明的属性的类型,其实际是指向objc_property结构体的指针
  • objc_property_attribute_t
    objc_property_attribute_t定义了属性的特性(attribute),它是一个结构体
  • 关联对象(Associated Object)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    static const void *kTapGestureRecognizer = &kTapGestureRecognizer;
    static const void *kDTActionHandlerTapBlockKey = &kDTActionHandlerTapBlockKey;

    //static NSString *cellIdentifier = @"cellIdentifier";

    @implementation ViewController

    - (void)viewDidLoad {
    [super viewDidLoad];
    [self setTapActionWithBlock:^{
    NSLog(@"TAP!!!!!!!!!!TAP!!!!!!!!!TAP!!!!!!!!!");
    }];
    }

    - (void)setTapActionWithBlock:(void (^)(void))block {
    UITapGestureRecognizer *gesture = objc_getAssociatedObject(self, kTapGestureRecognizer);
    if (!gesture) {
    gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(e__handleActionForTapGesture:)];
    [self.view addGestureRecognizer:gesture];
    objc_setAssociatedObject(self, kTapGestureRecognizer, gesture, OBJC_ASSOCIATION_RETAIN);
    }

    objc_setAssociatedObject(self, kDTActionHandlerTapBlockKey, block, OBJC_ASSOCIATION_COPY);
    }

    - (void)e__handleActionForTapGesture:(UITapGestureRecognizer *)gesture {
    if (gesture.state == UIGestureRecognizerStateRecognized) {
    void (^action)(void) = objc_getAssociatedObject(self, kDTActionHandlerTapBlockKey);
    if (action) {
    action();
    }
    }
    }
    @end

成员变量、属性的操作方法


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#import "MyObject.h"
#import <objc/runtime.h>

static NSMutableDictionary *map = nil;

@implementation MyObject

+ (void)load {
map = [NSMutableDictionary dictionary];

map[@"name1"] = @"name";
map[@"status1"] = @"status";
map[@"name2"] = @"name";
map[@"status2"] = @"status";
}

- (void)setDataWithDic:(NSDictionary *)dic {
[dic enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
NSString *propertyKey = [self propertyForKey:key];
if (propertyKey)
{
objc_property_t property = class_getProperty([self class], [propertyKey UTF8String]);

// TODO: 针对特殊数据类型做处理
NSString *attributeString = [NSString stringWithCString:property_getAttributes(property) encoding:NSUTF8StringEncoding];

NSLog(@"%@", attributeString);

[self setValue:obj forKey:propertyKey];
}
}];
}

- (NSString *)propertyForKey:(NSString *)key {
return map[key];
}

@end

坚持原创技术分享,您的支持将鼓励我继续创作!