如何实现给分类“添加成员变量”?

  • 默认情况下,因为分类底层结构的限制,不能添加成员变量到分类中。但可以通过关联对象来间接实现
  • 关联对象提供了以下API

  1> 添加关联对象

  void objc_setAssociatedObject(id object, const void * key,
  id value, objc_AssociationPolicy policy)

  2> 获得关联对象

  id objc_getAssociatedObject(id object, const void * key)

  3> 移除所有的关联对象

  void objc_removeAssociatedObjects(id object)

key的常见用法

objc_AssociationPolicy修饰符

给分类添加属性实例

假如已经有一个 XGPerson的类,现在我们需要扩展这个类,并且添加一个 age 属性

#import "XGPerson.h"

// 分类属性是不会生成 get\set 方法的,如果不重写这两个方法,就无法正常使用属性
@interface XGPerson (Test) @property (nonatomic,assign) int age; @end
#import "XGPerson+Test.h"
#import <objc/runtime.h> @implementation XGPerson (Test) - (void)setAge:(int)age{ // @selector(age) 这个参数只要传一个地址指针就可以
objc_setAssociatedObject(self, @selector(age), @(age), OBJC_ASSOCIATION_ASSIGN);
} - (int)age{ // 隐式参数
// _cmd = @selectior(age)
return [objc_getAssociatedObject(self, _cmd) intValue];
}

调用:

        XGPerson* p1 = [[XGPerson alloc]init];
p1.name = @"p1";
p1.age = ; XGPerson* p2 = [[XGPerson alloc]init];
p2.name = @"p2";
p2.age = ; NSLog(@"p1Name:%@ p1Age:%i----p2Name:%@ p2Age:%i",p1.name,p1.age,p2.name,p2.age);

输出:

-- ::38.666084+ 关联对象(增加分类属性)[:] p1Name:p1  p1Age:----p2Name:p2  p2Age:

关联对象的原理

  • 实现关联对象技术的核心对象有

  AssociationsManager
  AssociationsHashMap
  ObjectAssociationMap
  ObjcAssociation

  • objc4源码解读:objc-references.mm

  

  • 关联对象存储结构图

  1. 关联对象并不是存储在被关联对象本身内存中
  2. 关联对象存储在全局的统一的一个AssociationsManager中
  3. 设置关联对象为nil,就相当于是移除关联对象

移除对象关联引用源码:

当一个对象触发 dealloc 时会调用下面的代码:

可以看出,在调用 dealloc 方法时,不需要我们手动去删除 对象关联信息,它会自己去调用 删除对象关联信息

【OC底层】AssociatedObject 关联对象的更多相关文章

  1. OC - runtime 之关联对象

    header{font-size:1em;padding-top:1.5em;padding-bottom:1.5em} .markdown-body{overflow:hidden} .markdo ...

  2. AssociatedObject关联对象原理实现

    介绍 关联对象(AssociatedObject)是Objective-C 2.0运行时的一个特性,允许开发者对已经存在的类在扩展中添加自定义的属性.在实际生产过程中,比较常用的方式是给分类(Cate ...

  3. Objective-C——关联对象

    动态语言 OC是一种动态语言,它的方法,对象的类型都是到运行的时候才能够确定的.所以这就使得OC存在了关联对象这一强大的机制. 关联对象 所谓关联对象,其实就是我们在运行时对一个已存在的对象上面绑定一 ...

  4. 使用关联对象(AssociatedObject)为UIButton添加Block响应

    在开发中,要给UIButton添加点击事件的话,通常的做法是这样的 UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem]; [ ...

  5. 关联对象 AssociatedObject 完全解析

    我们在 iOS 开发中经常需要使用分类(Category),为已经存在的类添加属性的需求,但是使用 @property 并不能在分类中正确创建实例变量和存取方法. 不过,通过 Objective-C ...

  6. Runtime之成员变量&属性&关联对象

    上篇介绍了Runtime类和对象的相关知识点,在4.5和4.6小节,也介绍了成员变量和属性的一些方法应用.本篇将讨论实现细节的相关内容. 在讨论之前,我们先来介绍一个很冷僻但又很有用的一个关键字:@e ...

  7. Runtime - Associated Objects (关联对象) 的实现原理

    主要围绕3个方面说明runtime-Associated Objects (关联对象) 1. 使用场景 2.如何使用 3.底层实现 3.1  实现原理 3.2 关联对象被存储在什么地方,是不是存放在被 ...

  8. iOS Category 添加属性实现原理 - 关联对象

    iOS Category 添加属性实现原理 - 关联对象 RunTime为Category动态关联对象 使用RunTime给系统的类添加属性,首先需要了解对象与属性的关系.对象一开始初始化的时候其属性 ...

  9. Runtime - 关联对象使用方法及注意点

    大家都知道在分类里,可以间接的添加属性,运用runtime关联对象. 如下图,只是声明了btnClickedCount的set, get方法而已 并没有生成_btnClickedCount 成员变量, ...

随机推荐

  1. OpenGL学习—04--彩色立方体

        1.tutorial04.cpp // Include standard headers #include <stdio.h> #include <stdlib.h> ...

  2. 朴素贝叶斯文本分类实现 python cherry分类器

    贝叶斯模型在机器学习以及人工智能中都有出现,cherry分类器使用了朴素贝叶斯模型算法,经过简单的优化,使用1000个训练数据就能得到97.5%的准确率.虽然现在主流的框架都带有朴素贝叶斯模型算法,大 ...

  3. SQLite中7(8)形参的query语句的用法

    SQLite中7(8)形参的query语句的用法 我们先来看看这种7形参的query语句的形参列表: public Cursor query(String table, String[] column ...

  4. 水晶报表自定义纸张大小打印 (Crystal Report Print with custom paper size)

    System.Drawing.Printing.PrintDocument doc = new PrintDocument(); doc.PrinterSettings.PrinterName = & ...

  5. [翻译] FBNetworkReachability

    FBNetworkReachability You can use FBNetworkReachabilty class to get network reachability on iOS devi ...

  6. swift知识点 [1]

    swift知识点 [1] 循环遍历元素 三目运算符用途 Optional 与 ImplicitlyUnwrappedOptional 以及常规类型数据 is 的用法

  7. UNIX高级环境编程(8)进程环境(Process Environment)- 进程的启动和退出、内存布局、环境变量列表

    在学习进程控制相关知识之前,我们需要了解一个单进程的运行环境. 本章我们将了解一下的内容: 程序运行时,main函数是如何被调用的: 命令行参数是如何被传入到程序中的: 一个典型的内存布局是怎样的: ...

  8. Scala编程之访问修饰符

    private ,protected,public,在不加前两者声明时为public为公共式访问: private为私有式访问:protected为家族式访问,与Java一致. object Oute ...

  9. 【C#】#100 调用摄像头

    需求:由于项目需要获得用户的头像,所以需要用C#调用摄像头获取头像. 下面写一个调用摄像头的方法 案例:调用摄像头的一个DEMO[效果图] 使用的类库:AForge.dll   [Demo下载,Dem ...

  10. SDN 第一次作业

    你会选择作 网络编程 方向的程序员吗?为什么? 答: 可能会选择吧.看了那篇文章感觉网络编程的程序员和其他的程序员都并不简单,网络编程的程序员可能更要对网络的知识更加了解.我现在也有机会能接触网络方向 ...