iOS

(四)关联对象

2019-03-12  本文已影响22人  dandelionYD

引言

准备:首先搭建好可以跑runtime源码的过程,参考配置运行objc4-750和使用

gitHub_Demo

Animal.h
#import <Foundation/Foundation.h>
@interface Animal : NSObject
@property(nonatomic,strong)NSString * name;
@end

Animal.m
#import "Animal.h"
@implementation Animal
@end

Animal+category.h
#import "Animal.h"
@interface Animal (category)
@property(nonatomic,strong)NSString*address;
@end

Animal+category.m
#import "Animal+category.h"
@implementation Animal (category) 
@end

//此时我们发现系统会提示:
1.Property 'address' requires method 'address' to be defined - use @dynamic or provide a method implementation in this category
2.Property 'address' requires method 'setAddress:' to be defined - use @dynamic or provide a method implementation in this category

使用:main.h
#import <Foundation/Foundation.h>
#import "Animal+category.h"
#import  <objc/runtime.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Animal *animal = [[Animal alloc]init];    
        animal.name = @"啊黄";
        animal.address = @"地址"; //直接炸了
        NSLog(@"%@",animal.name);
        NSLog(@"%@",animal.address);
    }
    return 0;
}

发现:command+B 编译没有问题,
     command+R 运行就炸了

-[Animal setAddress:]: unrecognized selector sent to instance 0x1018159a0
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Animal setAddress:]: unrecognized selector sent to instance 0x1018159a0'
--------

至此我们发现:
 - 在分类里面添加属性(@property...),编译器只会生成set和get方法的声明,但是没有set和get方法的实现,而不会生成成员变量
 - 在分类里面是不能添加成员变量的

其实我们可以间接的去为分类添加成员变量的

如下:

Animal+category.h
#import "Animal.h"
@interface Animal (category)
@property(nonatomic,strong)NSString*address;
@property(nonatomic,assign)int age;
@end

Animal+category.m
#import "Animal+category.h"
#import <objc/runtime.h>
@implementation Animal (category)
-(void)setAddress:(NSString *)address{
    objc_setAssociatedObject(self, @selector(address), address, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
-(NSString *)address{
    return objc_getAssociatedObject(self, _cmd); ///_cmd = @selector(address)
}
-(void)setAge:(int)age{
     objc_setAssociatedObject(self, @selector(age), @(age), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
-(int)age{
    return [objc_getAssociatedObject(self, _cmd) intValue];
}
@end

使用:
#import <Foundation/Foundation.h>
#import "Animal+category.h"
#import  <objc/runtime.h>
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Animal *animal = [[Animal alloc]init];
        animal.name = @"啊黄";
        animal.address = @"地址";
        animal.age = 100;
        
        NSLog(@"%@",animal.name);
        NSLog(@"%@",animal.address);
        NSLog(@"%d",animal.age);   
    }
    return 0;
}
打印:
05.关联对象[22877:7181963] 啊黄
05.关联对象[22877:7181963] 地址
05.关联对象[22877:7181963] 100
static void *Mykey= &Mykey;
objc_setAssociatedObject(obj,Mykey,value,OBJC_ASSOCIATION_RETAIN_NONATOMIC)
objc_getAssociatedObject(obj,Mykey);
--------

static char Mykey;
objc_setAssociatedObject(obj,&Mykey,value,OBJC_ASSOCIATION_RETAIN_NONATOMIC)
objc_getAssociatedObject(obj,&Mykey);
--------

使用属性名作为key
objc_setAssociatedObject(obj,@"property",value,OBJC_ASSOCIATION_RETAIN_NONATOMIC)
objc_getAssociatedObject(obj,@"property");
--------

使用get方法的@selector作为key
objc_setAssociatedObject(obj,@selector(getter),value,OBJC_ASSOCIATION_RETAIN_NONATOMIC)
objc_getAssociatedObject(obj,@selector(getter));

补充:@selector(name)  返回的是某个结构体的指针(首地址)
关联对象_02.jpeg

友情链接:

上一篇 下一篇

猜你喜欢

热点阅读