Objective-C有两个扩展机制:Associative和Category。Category用来扩展类方法,Associative用于扩展属性。Associative机制的原理是把两个对象关联起来,让一个对象成为另外一个对象的一部分。它可以在不修改类的定义的前提下为其对象增加存储空间,这在我们无法访问类的源码时(例如给UILable添加一个selected的BOOL属性)是非常有用的。Associative基于关键字的,因此我们可以使用不同的关键字为任何对象添加任意多的Associative。Associative可以保证被关联的对象在对象的整个生命周期都是可用的。Associative基于runtime,是运行时里的东西,所以头文件需要引用#im port<objc/runtime.h>文件。

  Associative提供了三个方法:

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

详细介绍一下这几个方法,第一个用于设置关联的:

objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
注意的是返回值类型为Object类型,注意一些不是Object类型的例如:BOOL是结构类型。当碰到这种情况可以考虑通过中间类型来转换,如设置BOOL类型属性的时候可以转换为NSNumber类型,获取的时候再转换成BOOL类型即可。
四个参数分别是:源对象,关键字,关联对象和关联策略
关键字是一个void类型的指针,例如 static void * myKey = (void *)@"MyKey";每一个关联的关键字必须是唯一的。关联策略是枚举类型:
     enum{
OBJC_ASSOCIATION_ASSIGN;----------->@property(assign)----------->弱引用关联对象
OBJC_ASSOCIATION_COPY;------------->@property(copy,atomic)------>复制关联对象且为原子操作
OBJC_ASSOCIATION_COPY_NONATOMIC;--->@property(copy,nonatomic)--->复制关联对象且为非原子操作
OBJC_ASSOCIATION_RETAIN;----------->@property(strong,atomic)---->强引用关联对象且为原子操作
OBJC_ASSOCIATION_RETAIN_NONATOMIC;->@property(strong,nonatomic)->强引用且为非原子操作
}

第二个用于获取关联对象:

        objc_getAssociatedObject(id object, const void *key)
用于获取关联对象的值。这里需要注意的是返回值类型为Object类型,注意一些不是Object类型的例如:BOOL是结构类型

第三个 objc_removeAssociatedObjects(id object) 是断开关联,需要注意的是他会断开所有关联,所以不推荐这种方式。需要断开关联的时候使用objc_setAssociatedObject函数,传入nil值即可。

下面一个示例,我给UILable添加了一个表示选中状态的selected属性,自定义了类似于UIButton的选中非选中状态下设置背景色,字体色的方法。

.h文件

 #import <UIKit/UIKit.h>
#import <objc/runtime.h>
typedef enum{
ControlStateNormal,
ControlStateSelected,
}ControlState; @interface UILabel (CellLable) @property(nonatomic,assign)BOOL selected;//设置UILable的选中和非选中状态 default is NO -(void)setBackgroundColor:(UIColor *)backgroundColor forState:(ControlState)state ; -(void)setTextColor:(UIColor *)textColor forState:(ControlState)state ; @end

.m文件

 #import "UILabel+CellLable.h"

 static    UIColor * normalBackgroundColor = nil ;
static UIColor * selectedBackgorundColor = nil ;
static UIColor * normalTextColor = nil ;
static UIColor * selectedTextColor = nil ;
static UIColor * firstBackgroundColor = nil ;
static UIColor * firstTextColor = nil ; static BOOL isHaveSet = NO; //用于在未调用setSelected方法时 设置UILable的默认属性 //static char const myKey = '\a';
static void * myKey = (void *)@"MyKey"; @implementation UILabel (CellLable) @dynamic selected ;//动态绑定 声明自定义set get 方法,不自动生成 -(void)setSelected:(BOOL)selected{ #warning 注意 runtime 里边的objc_setAssociateObject 方法 第三个参数为object类型 BOOL属于结构类型 需要用NSNumber来转换
isHaveSet = YES; if (selected) { [self setBackgroundColor:nil forState:ControlStateSelected]; [self setTextColor:nil forState:ControlStateSelected]; }else if (!selected){ [self setBackgroundColor:nil forState:ControlStateNormal]; [self setTextColor:nil forState:ControlStateNormal];
} NSNumber * num = [NSNumber numberWithBool:selected]; objc_setAssociatedObject(self, &myKey, num, OBJC_ASSOCIATION_ASSIGN);
} -(BOOL)selected{ NSNumber * num = objc_getAssociatedObject(self, &myKey); return [num boolValue];
}
-(void)setBackgroundColor:(UIColor *)backgroundColor forState:(ControlState )state{ switch (state) {
case ControlStateNormal:
{
/** 当传递进来的是nil的时候,采取一种保护机制 **/
if (backgroundColor) { /** 记录上次传递进来的颜色属性 **/
normalBackgroundColor = backgroundColor ;
}
self.backgroundColor = normalBackgroundColor ;
}
break;
case ControlStateSelected:
{
if (backgroundColor) {
selectedBackgorundColor = backgroundColor ;
}
self.backgroundColor = selectedBackgorundColor ;
}
break ;
default:
break;
} if (!isHaveSet) { self.backgroundColor = normalBackgroundColor ;
}
} -(void)setTextColor:(UIColor *)textColor forState:(ControlState)state{ switch (state) {
case ControlStateNormal:
{
if (textColor) {
normalTextColor = textColor ;
}
self.textColor = normalTextColor ;
}
break;
case ControlStateSelected:
{
if (textColor) {
selectedTextColor = textColor ;
}
self.textColor = selectedTextColor ;
}
break ;
default:
break;
} if (!isHaveSet) {
self.textColor = normalTextColor ;
}
} @end

ViewController.m文件

 -(void)viewDidLoad{
UILabel * lable2 =[[UILabel alloc]initWithFrame:CGRectMake(, , , )]; lable2.textAlignment = NSTextAlignmentCenter ; lable2.layer.masksToBounds = YES ; lable2.layer.cornerRadius = ; lable2.selected = NO ; [lable2 setBackgroundColor:[UIColor colorWithRed:/255.0 green:/255.0 blue:/255.0 alpha:1.0] forState:ControlStateSelected];
[lable2 setBackgroundColor:[UIColor clearColor] forState:ControlStateNormal]; [lable2 setTextColor:[UIColor whiteColor] forState:ControlStateSelected];
[lable2 setTextColor:[UIColor blackColor] forState:ControlStateNormal]; [self.view addSubview:lable2];
}

iOS的扩展类,扩展属性的更多相关文章

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

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

  2. c#自定义ORM框架---(泛型&反射&实体类扩展属性<附带通用增、删、查、改>)

    该教材主要是运用到泛型.反射和实体类扩展属性 步骤一.建立扩展属性类 实体类扩展属性要继承Attribute基类完成 [AttributeUsage(AttributeTargets.Property ...

  3. iOS开发系列--App扩展开发

    概述 从iOS 8 开始Apple引入了扩展(Extension)用于增强系统应用服务和应用之间的交互.它的出现让自定义键盘.系统分享集成等这些依靠系统服务的开发变成了可能.WWDC 2016上众多更 ...

  4. OC分类(类目/类别) 和 类扩展 - 全解析

    OC分类(类目/类别) 和 类扩展 - 全解析   具体见: oschina -> MyDemo -> 011.FoundationLog-OC分类剖析 http://blog.csdn. ...

  5. OC-ARC,类扩展,block

    总结 标号 主题 内容 一 autorelease autorelease基本概念/自动释放池/autorelease基本使用 二 autorelease注意事项 注意点/应用场景 三 ARC 什么是 ...

  6. GenericAPIView类与几个扩展类的综合使用

    五个扩展类 扩展类 作用 封装的方法 状态码(成功,失败) ListModelMixin 查询多条数据 list 200 CreateModelMixin 新增一条数据 create 201,400 ...

  7. Django视图扩展类

    Django视图扩展类 扩展类必须配合GenericAPIView使用扩展类内部的方法,在调用序列化器时,都是使用get_serializer 需要自定义get.post等请求方法,内部实现调用扩展类 ...

  8. 关于iOS 类扩展Extension的进一步理解

    很多人可能会问  iOS的分类和扩展的区别,网上很多的讲解,但是一般都是分类讲的多,而这也是我们平常比较常用的知识:但是,对于扩展,总觉得理解的朦朦胧胧,不够透彻. 这里就讲一下我自己的理解,但是这个 ...

  9. ios开发总结:Utils常用方法等收集,添加扩展类,工具类方法,拥有很多方便快捷功能(不断更新中。。。)

    BOBUtils 工具大全 本人github开源和收集功能地址:https://github.com/niexiaobo [对ios新手或者工作一年以内开发人员很有用处] 常用方法等收集.添加扩展类. ...

随机推荐

  1. php技能考试每日一练

    PHP技術者認定 1, [日本語文字のメール送信] (2016年10月31日)以下のコードは桃家タローさん宛てにメールを送るためのものである.コード内の[(1)]に入る正しいものを1つ次の記述の中から ...

  2. JavaSE复习日记 : 循环终止语句(break/break outerFor/continue)

    最近没网,但攒了几天的博客,这次逮到机会发博客,直接三篇走起; /* * 循环终止语句: break/ break outerFor/ continue */ /* * break语句 * 1. 用于 ...

  3. 6.828 lab1 bootload

    MIT6.828 lab1地址:http://pdos.csail.mit.edu/6.828/2014/labs/lab1/ 第一个练习,主要是让我们熟悉汇编,嗯,没什么好说的. Part 1: P ...

  4. 利用汇编查看C++函数调用

    这篇文章的内容是一个老生常谈的问题----> 函数是如何被调用的. 本文用汇编代码研究函数调用的过程,参数调用的方式,函数值的返回. 1. 函数是如何实现调用的 函数的调用是用call 和 re ...

  5. php7 install memcached extension

    #download source code package from git $ git clone https://github.com/php-memcached-dev/php-memcache ...

  6. 【JQ成长笔记】jQuery Validate验证插件

    validate是一款很好的jq插件,提供了强大的验证功能,让客户端表单验证变得更简单,同时提供了大量的定制选项,满足应用程序各种需求.该插件捆绑了一套有用的验证方法,包括 URL 和电子邮件验证,同 ...

  7. firefox 自写底层扩展,源码简介

    还记得2010年的时候,那时候开始喜欢上了js,经常逛MDN 一开始写些简单的油猴脚本,慢慢的接触了扩展开发,发现用自己的js知识 加上firefox的插件API,可以完成好多功能. 看了很多插件的源 ...

  8. WIN7/8系统下程序接收不到WM_COPYDATA 消息的原因和解决

    在WIN7/win8,如果发送消息的程序用户权限低于和接收消息的程序,则消 息无法传递.发送程序必须等于或者等于接收程序的权限.如发送与接收 是同一个用户,或者发送是管理员帐户,接收是是普通用户,这样 ...

  9. CentOS 6下配置本地用户访问vsftpd并赋予写权限

    一.安装并测试可用性 1.安装命令 yum install vsftpd 2.配置防火墙,加入一行 -A INPUT -p tcp -m tcp --dport 21 -j ACCEPT 在其它机测试 ...

  10. Tex介绍

    TeX, LaTeX, XeTeX, PdfTeX等等 TeX 是一种宏语言.就像别的语言有库一样,TeX 语言有宏的集合.这些宏,就是用这个语言写出来的东西,供大家共用的.TeX 有个最基本的宏集合 ...