在iOS中,所有的UIControl标准控件使用到最普遍最传统的执行方法的方式就是Target-Action,中文一般称作目标-动作,是比较常用的一种设计模式。它的主要思想就是,在对象产生某个事件的特定时刻,给一个对象发送一个消息。就好像说『当talisk即将吃早饭的时候,swain去煎个蛋』。
其实Target-Action是很好用很方便的一个模式,但其最致命的一个缺点就是传值很麻烦,本文总结下这种模式的传值方式,并给出我认为最好的一个传值方式。
给对象加tag
这是最简单的一个方式,tag
是一个无符号整型值,贯穿于所有UIKit控件,给控件加上tag
,在action方法里可以取到sender
,对sender
做强制类型转换即可拿到tag
。
1
| [self.datePicker addTarget:self action:@selector(dateChange:) forControlEvents:UIControlEventValueChanged];
|
1 2 3 4 5
| - (void)dateChange:(id)sender { if (((UIDatePicker *)sender).tag) { NSLog(@"tag0"); } }
|
由于tag
是个无符号整型数值,也仅仅能传递一些简单数据。
sender
就是发起行为的对象,就像上面这段代码所写,当datePicker
的值发生变化的时候,调用self
的dateChange:
方法,这个方法默认参数就是sender
。
给父类做category
通过category给父类加上一些方法,使子类对象能够携带一些数据,这样对于开发者来说就很自由了。
1 2 3 4 5 6 7
| #import <Foundation/Foundation.h> @interface NSObject (Extension) @property (nonatomic,retain)NSDictionary *userInfo; @end
|
在头文件中,注明category和名称,加上我们需要使用的数据的property。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| #import "NSObject+Extension.h" #import <objc/runtime.h> @implementation NSObject (Extension) - (void)setUserInfo:(NSDictionary *)_userInfo { objc_setAssociatedObject(self, @"userInfo", _userInfo, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } - (id)userInfo { return objc_getAssociatedObject(self, @"userInfo"); } @end
|
在实现文件中,要用到Objective-C的Runtime黑魔法了,通过使用objc_getAssociatedObject
和objc_setAssociatedObject
两个运行时函数的使用,动态地向NSObject
根类中添加了属性,这样,只要是继承自NSObject
并且引用了这个Category的地方,我们都可以给对象添加userInfo这个属性,意味着我们想传递什么就可以传递什么了。
在写完这个Category后,我们在需要传值的地方,给对象设置好userInfo,即可。
1 2
| [self.datePicker addTarget:self action:@selector(dateChange:) forControlEvents:UIControlEventValueChanged]; [self.datePicker setUserInfo:@{@"from": [NSDate date], @"to": [NSDate date]}];
|
1 2 3
| - (void)dateChange:(id)sender { NSLog(@"%@", ((UIDatePicker *)sender).userInfo); }
|