美文网首页iOS
(四)关联对象

(四)关联对象

作者: dandelionYD | 来源:发表于2019-03-12 16:53 被阅读22次

引言

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

gitHub_Demo

  • 我们试试给category添加属性看看呢?
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
  • 可见使用【关联对象】可以添加成员变量的哟

    API如下:

    添加关联对象
    void objc_setAssociatedObject(id object, const void *key, 
                                id value, objc_AssociationPolicy policy)                            
    获得关联对象
    id objc_getAssociatedObject(id object, const void *key) 
    
    移除所有的关联对象
    void objc_removeAssociatedObjects(id object) 
    
    //文件处于:objc-runtime.mm
    
  • 其中key的使用定义

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)  返回的是某个结构体的指针(首地址)
  • objc_AssociationPolicy的说明
    • objc_AssociationPolicy 对应的修饰符
    • OBJC_ASSOCIATION_ASSIGN -----> assign
    • OBJC_ASSOCIATION_RETAIN_NONATOMIC. ----->strong,nonatomic
    • OBJC_ASSOCIATION_COPY_NONATOMIC ----->copy,nonatomic
    • OBJC_ASSOCIATION_RETAIN ----->strong,actomic
    • OBJC_ASSOCIATION_COPY ----->copy,actomic
  • 关联对象的原理(可以点进去见源码)


    关联对象_01.jpeg
关联对象_02.jpeg

友情链接:

相关文章

  • (四)关联对象

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

  • Swift 为分类增加属性objc_getAssociated

    OC 获取关联对象 Swift 获取关联对象——错误的写法 Swift 获取关联对象——正确的写法 设置关联对象 ...

  • iOS runtime关联对象 objc_setAssociat

    关联对象的作用: 关联对象可以给某个对象关联一个或者多个其他对象,这些对象通过健来区分。 创建存储关联对象objc...

  • 关联对象

    关联对象的方式 关联对象源码基本思路 关联对象的结构:AssociationsHashManager // Ass...

  • 关联对象

    关联对象原理 关联对象并不是存储在被关联对象本身内存中,关联对象存储在全局的统一的一个AssociationsMa...

  • objc_setAssociatedObject和objc_ge

    这四个后面的参数分别表示:源对象,关键字,关联的对象和一个关联策略。关联策略是一个枚举 第一个参数为源对象,第二个...

  • iOS 关联对象

    概述 关联对象顾名思义,就是给对象关联对象的意思,一个对象可以关联多个其他对象,这些对象通过key来区分,存储对象...

  • 关联对象

    关联对象会用被关联对象作为key,将关联对象存储到全局的哈希表里。 AssociationHashMap Asso...

  • iOS关联对象技术原理

    iOS关联对象技术原理 iOS关联对象技术原理

  • 关联对象

    分类里面添加成员变量, 分类里面是不能直接添加成员变量的,但是可以通过runtime间接添加成员变量。 为什么...

网友评论

    本文标题:(四)关联对象

    本文链接:https://www.haomeiwen.com/subject/fymnpqtx.html