iOS学习系列 - 扩展机制category与associative
iOS学习系列
- 扩展机制category与associative
category与associative作为objective-c的扩展机制的两个特性,category即类型,可以通过它来扩展方法;associative,可以通过它来扩展属性;在iOS开发中,可能category比较常见,相对的associative,就用的比较少,要用它必须使用<objc/runtime.h>的头文件,然后就可以自由使用objc_getAssociatedObject以及objc_setAssociatedObject,我们来看下这两个方法:

__OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_1);
OBJC_EXPORT id objc_getAssociatedObject(id object, const void *key)
__OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_1);

另外还有一个方法:

__OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_1);

objc_getAssociatedObject、objc_setAssociatedObject、objc_removeAssociatedObjects都是Obj-c中的外联方法,object 参数作为待扩展的对象实例,key作为该对象实例的属性的键,而value就是对象实例的属性的值,policy作为关联的策略,它的枚举包括:

OBJC_ASSOCIATION_ASSIGN = 0,
OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1,
OBJC_ASSOCIATION_COPY_NONATOMIC = 3,
OBJC_ASSOCIATION_RETAIN = 01401,
OBJC_ASSOCIATION_COPY = 01403
};

具体我就多说了,可以看得懂的。
另外,objc_removeAssociatedObjects可以删除指定对象实例的所有扩展属性。
现在看一个简单的例子:(引用网上的例子:http://code4app.com/ios/Block-UI/504fe65d6803faa33f000003 )
这里,定义了一个"alert view"的按钮:

[viewController.view addSubview:button];
button.frame = CGRectMake(50, 50, 100, 44);
[button setTitle:@"alert view" forState:UIControlStateNormal];

现在对UIButton通过使用category对其进行方法扩展:

…...
- (void)handleControlEvent:(UIControlEvents)event withBlock:(void(^)(id sender))block {
NSString *methodName = [UIControl eventName:event];
NSMutableDictionary *opreations = (NSMutableDictionary*)objc_getAssociatedObject(self, &OperationKey);
if(opreations == nil)
{
opreations = [[NSMutableDictionary alloc] init];
objc_setAssociatedObject(self, &OperationKey, opreations, OBJC_ASSOCIATION_RETAIN);
}
[opreations setObject:block forKey:methodName];
[self addTarget:self action:NSSelectorFromString(methodName) forControlEvents:event];
}

objc_getAssociatedObject,objc_setAssociatedObject进行属性扩展:
OperationKey是一个字符类型,这里表示一个键,如果Opreations为空,会setAssociatedObject一个新的opreations对象到对应键的值中间。
addTarget:action:forControlEvents对于触摸事件进行目标绑定。
NSSelectorFromString(methodName) 将触发方法:

-(void)UIControlEventTouchDownRepeat{[self callActionBlock:UIControlEventTouchDownRepeat];}
-(void)UIControlEventTouchDragInside{[self callActionBlock:UIControlEventTouchDragInside];}
-(void)UIControlEventTouchDragOutside{[self callActionBlock:UIControlEventTouchDragOutside];}
-(void)UIControlEventTouchDragEnter{[self callActionBlock:UIControlEventTouchDragEnter];}
-(void)UIControlEventTouchDragExit{[self callActionBlock:UIControlEventTouchDragExit];}
-(void)UIControlEventTouchUpInside{[self callActionBlock:UIControlEventTouchUpInside];}
-(void)UIControlEventTouchUpOutside{[self callActionBlock:UIControlEventTouchUpOutside];}
-(void)UIControlEventTouchCancel{[self callActionBlock:UIControlEventTouchCancel];}
-(void)UIControlEventValueChanged{[self callActionBlock:UIControlEventValueChanged];}
-(void)UIControlEventEditingDidBegin{[self callActionBlock:UIControlEventEditingDidBegin];}
-(void)UIControlEventEditingChanged{[self callActionBlock:UIControlEventEditingChanged];}
-(void)UIControlEventEditingDidEnd{[self callActionBlock:UIControlEventEditingDidEnd];}
-(void)UIControlEventEditingDidEndOnExit{[self callActionBlock:UIControlEventEditingDidEndOnExit];}
-(void)UIControlEventAllTouchEvents{[self callActionBlock:UIControlEventAllTouchEvents];}
-(void)UIControlEventAllEditingEvents{[self callActionBlock:UIControlEventAllEditingEvents];}
-(void)UIControlEventApplicationReserved{[self callActionBlock:UIControlEventApplicationReserved];}
-(void)UIControlEventSystemReserved{[self callActionBlock:UIControlEventSystemReserved];}
-(void)UIControlEventAllEvents{[self callActionBlock:UIControlEventAllEvents];}

注意到这里会去执行callActionBlock:方法:

NSMutableDictionary *opreations = (NSMutableDictionary*)objc_getAssociatedObject(self, &OperationKey);
if(opreations == nil) return;
void(^block)(id sender) = [opreations objectForKey:[UIControl eventName:event]];
if (block) block(self);
}

最终会从扩展属性中得到^block,关于^block可以参考:http://blog.csdn.net/pjk1129/article/details/6577097
最后调用:

UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"alert"
message:nil
delegate:nil
cancelButtonTitle:@"ok"
otherButtonTitles:@"other",nil];
}];

点击按钮就会触发一个block函数。
这样就实现了objective-c的两种扩展机制。
iOS学习系列 - 扩展机制category与associative的更多相关文章
- IOS中扩展机制Category和associative
在ios开发中,有时候会遇到以下的问题,需要在一个类中添加自己的一些属性和方法.一般的做法是重写一个类来继承它,但是有时候就只是需要添加一些简单的属性和方法,那么这样做就显得过于麻烦,其实在IOS中还 ...
- iOS学习系列-Apache服务器的配置
配置Apache服务器 一.目的 能够有一个测试的服务器,不是所有的特殊网络服务都能找到免费得! 二.为什么我们要用"Apache"? Apache是目前使用最广的web服务器 M ...
- iOS开发系列--扩展--播放音乐库中的音乐
众所周知音乐是iOS的重要组成播放,无论是iPod.iTouch.iPhone还是iPad都可以在iTunes购买音乐或添加本地音乐到音乐 库中同步到你的iOS设备.在MediaPlayer.fram ...
- iOS学习笔记06—Category和Extension
iOS学习笔记06—Category和Extension 一.概述 类别是一种为现有的类添加新方法的方式. 利用Objective-C的动态运行时分配机制,Category提供了一种比继承(inher ...
- iOS开发系列--App扩展开发
概述 从iOS 8 开始Apple引入了扩展(Extension)用于增强系统应用服务和应用之间的交互.它的出现让自定义键盘.系统分享集成等这些依靠系统服务的开发变成了可能.WWDC 2016上众多更 ...
- iOS学习笔记之Category
iOS学习笔记之Category 写在前面 Category是类别(也称为类目或范畴),使用Category,程序员可以为任何已有的类添加方法.使用类别可以对框架提供的类(无法获取源码,不能直接修改) ...
- iOS开发系列--通知与消息机制
概述 在多数移动应用中任何时候都只能有一个应用程序处于活跃状态,如果其他应用此刻发生了一些用户感兴趣的那么通过通知机制就可以告诉用户此时发生的事情.iOS中通知机制又叫消息机制,其包括两类:一类是本地 ...
- MVC学习系列——ModelBinder扩展
在MVC系统中,我们接受数据,运用的是ModelBinder 的技术. MVC学习系列——ActionResult扩展在这个系列中,我们自定义了XmlResult的返回结果. 那么是不是意味着能POS ...
- IOS学习之IOS沙盒(sandbox)机制和文件操作
IOS学习之IOS沙盒(sandbox)机制和文件操作(一) 1.IOS沙盒机制 IOS应用程序只能在为该改程序创建的文件系统中读取文件,不可以去其它地方访问,此区域被成为沙盒,所以所有的非代码文件都 ...
随机推荐
- java 遍历
LinkedList倒序遍历 public List<Integer> getNewsFeed(int userId) { List<Integer> res = new Ar ...
- hbase字典顺序存储
rowkey rowkey是行的主键,而且hbase只能用个rowkey,或者一个rowkey范围即scan来查找数据.所以 rowkey的设计是至关重要的,关系到你应用层的查询效率.我们知 ...
- Layui 获取表单提交数据
HTML<div class="layui-card-header layuiadmin-card-header-auto"> <form class=" ...
- spring源码学习之容器的扩展(一)
在前面的章节,我们一直以BeanFactory接口以及它的默认实现XmlBeanFactory为例进行解析,但是,spring还提供了另一个接口ApplicationContext,用于扩展BeanF ...
- Functional Programming Contest - September'14
比赛链接 A题 -- Enter your code here. Read input from STDIN. Print output to STDOUT main = do x <- get ...
- mysql 无法存储joda time的datetime类型
com.mysql.jdbc.MysqlDataTruncation: Data truncation: Incorrect datetime value: '\xAC\xED\x00\x05sr\x ...
- GIT → 02:Git和Svn比较
2.1 SVN介绍 2.1.1 SVN简介 SVN 属于集中式版本管理控制系统,服务器中保存了所有文件的不同版本,而协同工作人员通过连接svn服务器,提取出最新的文件,获取提交更新.Subversio ...
- Mac下载Navicat premium提示文件损坏的解决方案
首先打开终端,执行: sudo bash 这时会提示你输入你的账户密码, 输入完后就切换到了 root 用户,然后执行: xattr -cr /Applications/Navicat\ Premiu ...
- linux(centos) 下安装phpstudy 如何命令行进入mysql
配置了phpstudy 可是进不去MySQL 老是报-bash: mysqld: command not found 解决方法:在Linux环境下运行:ln -s /phpstudy/mysql/bi ...
- Git pull 强制覆盖本地文件 - CSDN博客
Git pull 强制覆盖本地文件 原创 2015年11月16日 22:07:56 标签: git git fetch --all git reset --hard origin/master git ...