遇到一个问题,写了一个分类,但原先类的属性不够用。添加一个属性,调用的时候崩溃了,说是找不到getter、setter方法。查了下文档发现,OC的分类允许给分类添加属性,但不会自动生成getter、setter方法。有没有解决方案呢?有,通过运行时建立关联引用。接下来以添加一个这样的属性为例:

  1. @property (nonatomic, copy) NSString *str;

1、引入运行时头文件。

  1. #import <objc/runtime.h>

2、在匿名分类或者头文件中添加属性。区别是:匿名分类中添加的是私有属性,只在本类中可以使用,类的实例中不可以使用。头文件中添加的在类的实例中也可以使用。

  1. //分类的头文件
  2. @interface ClassName (CategoryName)
  3. //我要添加一个实例也可以访问的变量所以就写在这里了
  4. @property (nonatomic, strong) NSString *str;
  5. @end
  6.  
  7. //匿名分类
  8. @interface ClassName ()
  9.  
  10. @end

3、在实现里面写要添加属性的getter、setter方法。

  1. @implementation ClassName (CategoryName)
  2.  
  3. -(void)setStr:(NSString *)str
  4. {
  5. objc_setAssociatedObject(self, &strKey, str, OBJC_ASSOCIATION_COPY);
  6. }
  7.  
  8. -(NSString *)str
  9. {
  10. return objc_getAssociatedObject(self, &strKey);
  11. }
  12. @end

setStr:方法中使用了一个objc_setAssociatedObject的方法,这个方法有四个参数,分别是:源对象,关联时的用来标记是哪一个属性的key(因为你可能要添加很多属性),关联的对象和一个关联策略。

用来标记是哪一个属性的key常见有三种写法,但代码效果是一样的,如下:

  1. //利用静态变量地址唯一不变的特性
  2. 1static void *strKey = &strKey;
  3.  
  4. 2static NSString *strKey = @"strKey";
  5.  
  6. 3static char strKey;

关联策略是个枚举值,解释如下:

  1. enum {
  2. OBJC_ASSOCIATION_ASSIGN = 0, //关联对象的属性是弱引用
  3.  
  4. OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, //关联对象的属性是强引用并且关联对象不使用原子性
  5.  
  6. OBJC_ASSOCIATION_COPY_NONATOMIC = 3, //关联对象的属性是copy并且关联对象不使用原子性
  7.  
  8. OBJC_ASSOCIATION_RETAIN = 01401, //关联对象的属性是copy并且关联对象使用原子性
  9.  
  10. OBJC_ASSOCIATION_COPY = 01403 //关联对象的属性是copy并且关联对象使用原子性
  11. };

4、完成后的整体代码如下:

.h文件

  1. //分类的头文件
  2. @interface ClassName (CategoryName)
  3. @property (nonatomic, strong) NSString *str;
  4. @end

.m文件

  1. //实现文件
  2. #import "ClassName + CategoryName.h"
  3. #import <objc/runtime.h>
  4.  
  5. static void *strKey = &strKey;
  6.  
  7. @implementation ClassName (CategoryName)
  8. -(void)setStr:(NSString *)str
  9. {
  10. objc_setAssociatedObject(self, & strKey, str, OBJC_ASSOCIATION_COPY);
  11. }
  12.  
  13. -(NSString *)str
  14. {
  15. return objc_getAssociatedObject(self, &strKey);
  16. }
  17. @end

  

给分类(Category)添加属性的更多相关文章

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

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

  2. category添加属性

    category添加属性 面试题 Category的实现原理,以及Category为什么只能加方法不能加属性. Category中有load方法吗?load方法是什么时候调用的?load 方法能继承吗 ...

  3. 【原】iOS动态性(一):动态添加属性的方法——关联(e.g. 向Category添加属性)

    想到要如何为所有的对象增加实例变量吗?我们知道,使用Category可以很方便地为现有的类增加方法,但却无法直接增加实例变量.不过从Mac OS X v10.6开始,系统提供了Associative ...

  4. iOS动态性:动态添加属性的方法——关联(e.g. 向Category添加属性)

    想到要如何为所有的对象增加实例变量吗?我们知道,使用Category可以很方便地为现有的类增加方法,但却无法直接增加实例变量.不过从Mac OS X v10.6开始,系统提供了Associative ...

  5. 通过运行时动态给OC分类添加属性

    #import <UIKit/UIKit.h> /** iOS 开发中,分类默认不允许保存属性 如果在分类中,定义一个属性,需要自己实现 getter & setter 方法,而且 ...

  6. iOS分类(category),类扩展(extension)—史上最全攻略

    背景: 在大型项目,企业级开发中多人同时维护同一个类,此时程序员A因为某项需求只想给当前类currentClass添加一个方法newMethod,那该怎么办呢? 最简单粗暴的方式是把newMethod ...

  7. iOS之Category关联属性

    Objective-C /** 原文件 */ // Person.h #import <Foundation/Foundation.h> @interface Person : NSObj ...

  8. category类别中添加属性

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #c91b13 } p.p2 { margin: 0.0px 0. ...

  9. 给category添加基本数据类型属性

    给category添加基本数据类型属性 说明 通常,我们添加属性都是通过对象扩展来实现的,其实,我们也可以用runtime来添加基本数据类型的属性 源码 // // UIView+AnimationP ...

随机推荐

  1. StringHelpers

    public class StringHelpers { public const char QUERY_STRING_DELIMITER = '&'; private static Rijn ...

  2. 打开URL操作

    /* * 打开 url 的两种方法 */ public class OpenUrl { public static void main(String[] args) { String url = &q ...

  3. linux修改主机名

    查看机器名:uname -a 修改机器名: redhat中修改主机名 第一步:#hostname oratest 第二步:修改/etc/sysconfig/network中的hostname 第三步: ...

  4. PHPcurl抓取AJAX异步内容(转载)

    PHPcurl抓取AJAX异步内容 其实抓ajax异步内容的页面和抓普通的页面区别不大.ajax只不过是做了一次异步的http请求,只要使用firebug类似的工具,找到请求的后端服务url和传值的参 ...

  5. lfs遇到的一些问题--编制LFS

    1.chroot后不要再打开新的终端了,没法用,还可能使系统崩溃.另外如果需要去睡觉,重启后要再次挂载并填充/dev和挂载虚拟内核文件系统,并再次运行chroot,可以将下列命令保存为脚本,重启后一次 ...

  6. Windows和Ubuntu双系统,修复UEFI引导的两种办法

    查看ubuntu是否是从 efi/uefi 启动的方法:  若 /sys/firmware/efi 存在则是,否则不是.shell命令: [ -d /sys/firmware/efi ] && ...

  7. Nginx+tomcat负载均衡并动静态分离

    Nginx使用正则表达式配置location,指定某些后缀的文件直接从文件路径中找(如*.jpg直接去C:/XX/XX/XX/img下找),其他的请求转发给tomcat 同时可以配置多个tomcat ...

  8. AVL树的左旋右旋理解 (转)

    AVL树是最先发明的自平衡二叉查找树.在AVL树中任何节点的两个子树的高度最大差别为一,所以它也被称为高度平衡树.查找.插入和删除在平均和最坏情况下都是O(log n).增加和删除可能需要通过一次或多 ...

  9. use SWF / Flash in cocos2d-x; cocos2d(cocos2d-x) 直接播放flash / SWF文件

    前段时间移植一个页游到手游,原先页游的项目里面有1000+的Flash人物,宠物动画,特效. 这要是全部重新做一遍,还不累死人?所以就想干脆直接在Cocos2d(x)里面播放SWF文件.(包括场景,过 ...

  10. BABOK - 企业分析(Enterprise Analysis)

    BABOK - 企业分析(Enterprise Analysis)概要 发表于2013年10月9日由周金根 描述 企业分析描述我们如何捕捉.提炼并明晰业务需要,并定义一个可能实现这些业务需要的一个方案 ...