本文由DevDiv Vincent (vincent@devdiv.com)原创,转载请联系作者!
最近DevDiv论坛上有网友在问如何自定义event,
自定义event在其他平台,如Windows Phone上实现自定义控件是很常见的,其实在iOS中也是支持自定义event的。
原理分析如下:
1. 我们先来看看自定义消息id:
我们来看看UIControl的定义,我们打算自定义一个control,继承自它
在UIControl中大家可以看到以下enum:
[代码]c#/cpp/oc代码:
1 | UIControlEventAllTouchEvents = 0x00000FFF, |
2 | UIControlEventAllEditingEvents = 0x000F0000, |
3 | UIControlEventApplicationReserved = 0x0F000000, |
4 | UIControlEventSystemReserved = 0xF0000000, |
5 | UIControlEventAllEvents = 0xFFFFFFFF |
其中我们可以通过UIControlEventApplicationReserved自定义一个event(实际上event就是一个数字,或者叫消息id)
如果你把这个十六进制表示改为二级制那么,它的值为0x0F000000 = 00001111 00000000 00000000 00000000
这个定义的意思是表示有4位1111是为我们保留可以自定义消息的,所以我们能够自定义的消息id依次为
[代码]c#/cpp/oc代码:
1 | 0x00000001<<27 = 00001000 00000000 00000000 00000000 |
2 | 0x00000001<<26 = 00000100 00000000 00000000 00000000 |
3 | 0x00000001<<25 = 00000010 00000000 00000000 00000000 |
4 | 0x00000001<<24 = 00000001 00000000 00000000 00000000 |
2. 消息action注册
在iOS中我们一般通过addTarget:action:forControlEvents:注册一个event的处理函数
A control maintains an internal dispatch table: for each control event there is some number of target-action pairs, of which the action is a selector (the name of a method) and the target is the object to which that message is to be sent. When a control event occurs, the control consults its dispatch table, finds all the targer-action pairs associated with that control event, and sends each action message to the corresponding target.
也就是说控件内部有一个dispatch table,维护了event和action对应关系。
我们调用addTarget:action:forControlEvents:时候就会在这张表中增加一条记录
3. 消息触发
我们可以通过UIControl的sendActionsForControlEvents:触发一个event
一旦évent触发,那么ta它会查找dispatch table,调用相应的action
代码示例:
1. 我们先创建一个DevDivCustomEvent的工程
创建一个CustomControl,继承在UIControl;并定义一个自定义消息UIControlEventCustom1,代码如下
[代码]c#/cpp/oc代码:
09 | #import <UIKit/UIKit.h> |
12 | UIControlEventCustom1 = 0x00000001<<25, |
15 | @ interface CustomControl : UIControl |
2. 在ViewController.h中声明一个CustomControl属性
[代码]c#/cpp/oc代码:
1 | @property (nonatomic, strong) CustomControl *customControl; |
3. 打开ViewController.m文件,在viewDidLoad中创建CustomControl的实例,并为UIControlEventTouchUpInside和UIControlEventCustom1注册action,代码如下:
[代码]c#/cpp/oc代码:
07 | self.view.backgroundColor = [UIColor whiteColor]; |
10 | self.customControl = [[CustomControl alloc] initWithFrame: |
11 | CGRectMake(100, 100, 100, 100)]; |
12 | self.customControl.backgroundColor = [UIColor greenColor]; |
15 | [self.customControl addTarget:self action:@selector(customControlTouchUpInside:) forControlEvents:UIControlEventTouchUpInside]; |
17 | [self.customControl addTarget:self action:@selector(customControlCustom1Handler:) forControlEvents:UIControlEventCustom1]; |
19 | [self.view addSubview:self.customControl]; |
4. 在customControlTouchUpInside:触发UIControlEventCustom1,代码如下:
[代码]c#/cpp/oc代码:
2 | - ( void )customControlTouchUpInside:(CustomControl*)paramSender |
4 | [paramSender sendActionsForControlEvents:UIControlEventCustom1]; |
5. 如果customControlCustom1Handler:能够执行,说明注册event action和trigger event都成功了,代码如下:
[代码]c#/cpp/oc代码:
1 | - ( void )customControlCustom1Handler:(CustomControl*)paramSender |
3 | NSLog( @"DevDiv.com Custom Event Triggered!" ); |
6. 执行工程,可以发现第5步中的Log可以打印出来,效果如图:
7. 代码下载: