Target/action
1.定义:Target/action模式是为了方便开发者管理同一类的不同对象的,定义一个ActionView类,继承自UIView
例子:假设使用ActionView创建不同的视图,redView、greenView、blueView三个对象,分别让三个视图响应不同的事件,redView改变自身背景颜色,greenView改变父视图背景颜色,blueView改变自身位置。
解决方案:
方法1. 我们可以在设定的时候给redView、greenView、blueView 设定 tag 值 然后再用 switch 调用
// 1.创建根视图控制器:ActionViewController 继承 UIViewController
// 2.修改 AppDelegate 里的根视图控制器
ActionViewController *actionVC = [[ActionViewController alloc]init];
self.window.rootViewController = actionVC;
[actionVC release];
// 3.在根视图的控制器中创建三个视图:
// 红色
ActionView *redView = [[ActionView alloc]initWithFrame:CGRectMake(20, 20, 280, 100)];
redView.backgroundColor = [UIColor redColor];
[self.view addSubview:redView];
redView.tag = 100;
[redView release];
//绿色
ActionView *greenView = [[ActionView alloc]initWithFrame:CGRectMake(20, 130, 280, 100)];
greenView .backgroundColor = [UIColor greenColor];
greenView.tag = 101;
[self.view addSubview:greenView];
[greenView release];
//蓝色
ActionView *blueView = [[ActionView alloc]initWithFrame:CGRectMake(20, 250, 280, 100)];
blueView.backgroundColor = [UIColor blueColor];
[self.view addSubview:blueView];
[blueView release];
// 4. cmd+n 创建 ActionView 继承 UIView
.m 中
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
switch (self.tag) {
case 100:
self.backgroundColor = [UIColor randomColor];
break;
case 101:
self.superview.backgroundColor = [UIColor randomColor];
break;
case 102:
self .center = CGPointMake(arc4random()%101+100, arc4random()%301+100);
default:
break;
}
}
注意:笨重的 ActionView 的处理 不够灵活 每次创建一个新视图及对应的响应的处理事件 都要造成 ActionView 里的源代码 给视图添加不同的处理事件
思考:如何像 button一样灵活 ??
方法2,使用target/action模式开发。具体思想,让ActionView的对象调用一个方法,能够根据不同的对象执行不同的方法。
// ① 在ActionView类的.h文件中声明一个方法(因为外面需要使用这个方法,所以需要声明)
- (void)addTarget:(id)target action:(SEL)action;
//②,在ActionView类的.m文件中实现这个方法,实现这个方法前我们要明白这个方法的两个参数的含义,
//target指的是谁来完成这个方法,
//action指的是具体什么方法,
//所以我们需要在.m文件中定义两个变量来存放这两个参数。
@interface ActionView()
{
id _target;// 存储响应目标(对象)
SEL _action;//存储响应事件(方法)
}
//注意:@interface ActionView() 是在.m中实现的,所以这两个变量是私有变量,外界无法访问
实现声明的方法
- (void)addTarget:(id)target action:(SEL)action
{
_target = target;
_action = action;
}
③,我们要实现的就是在点击某个视图的时候响应某个方法,所以我们需要在ActionView的.m文件中的方法里实现方法
- (void)touches:(NSSet *)touches withEvent:(UIEvent*)event{
[_target performSelector:_action withObject:self];
}
//注: _target、_action中存放的是外面调用- (void)addTarget:(id)target action:(SEL)action;方法时传进来的值,
//self指的是ActionView的一个对象。
//可以解释为:_target 帮 self 做一件事_action
④,调用- (void)addTarget:(id)target action:(SEL)action;方法
我们在试图控制器中创建了一个ActionView类的redView对象,使用redView对象调用我们设置的方法
ActionView *redView = [[ActionView alloc]initWithFrame:CGRectMake(20, 20, 280, 100)];
redView.backgroundColor = [UIColor redColor];
[self.view addSubview:redView];
[redView addTarget:self action:@selector(changeMyselfColor:)];//方法
[redView release];
注:其实和方法1的创建视图一样 多了一个方法
// [redView addTarget:self action:@selector(changeMyselfColor: )];
//这句话的意思是,让一个对象self(视图控制器对象)调用一个方法 (changeMyselfColor:)就是我们的方法
#pragma mark ----实现方法------
-(void)changeMyselfColor:(ActionView *)view{
view.backgroundColor = [UIColor randomColor];
}
总结,执行顺序:④ -> ① -> ② ->③ -> ⑤,这种方式只能实现一个让target对一个action,耦合性较高,如果要实现一对多需要使用代理
下面将代理
1.重新创建了一个UIView的子类DelegateView
①,要使用代理我们首先要有一个协议,所以第一步制订协议。
制订协议有两种方法,如果这个协议是为了让多个类遵循的话,就创建一个协议文件protocol,如果只是一个类让别人帮自己做事情那么就在这个类的.h中制订协议。
在DelegateView类的.h文件中制订协议,
@class DelegateView;//告诉系统 使用了这个类
@protocol DelegateViewDelegate <NSObject>
//1.制定协议(为了写一些方法)
@optional//可选实现
//delegateView 类里的 view 如果是其他类 就会换成其他类的名字
- (void)changeMyselfColor:(DelegateView *)view;
-(void) changeSuperviewColor:(DelegateView *)view;
-(void) changeMyselfLocation:(DelegateView *)view;
@end
@interface DelegateView : UIView
//2.指定代理
@property (nonatomic,assign) iddelegate;
//?为什么用 dalegate 命名 这么是命名方法 当有在 controller 使用 delegate的时候 就会变成引入的那个参数 比如我们现在的 redView.delegate = self 里 self; 如果你这个地方不是 delegate 那么你在 controller 里面要用的时候 就点 你在这里设的名字
③ 问题来了 什么时候使用代理?
╮(╯▽╰)╭ 当然是我们需要的时候了 比如点击视图的时候 所以要在DelegateView类的.m文件中实现方法
- (void)touches:(NSSet *)touches withEvent:(UIEvent*)event{// 但是要先判断 判断代理有没有执行协议中对应的方法
BOOL isResponder = [_delegate respondsToSelector:@selector(changeMyselfColor:)];
// 代理执行协议方法的时机 但是要先判断
if (isResponder) {
[_delegate changeMyselfColor:self];
//这里的self指的是DelegateView类的一个对象
}
}
④,协议指定完毕,我们需要找个人来遵循这个协议,
我们让视图控制器遵循这个协议 DelegateUIViewController
1.创建一个DelegateUIViewController类
在DelegateUIViewController. h 中
@interface DelegateUIViewController : UIViewController <DelegateViewDelegate>//需要引入协议所在类的头文件
@end
在. m 中 指定代理对象
DelegateView *redView = [[DelegateView alloc]initWithFrame:CGRectMake(20, 30, 280, 100)];
redView.backgroundColor = [UIColor redColor];
//指定代理对象
redView.delegate = self;
[self .view addSubview:redView];
[redView release];
#pragma mark-----代理方法------
-(void)changeMyselfColor:(DelegateView *)view{
view.backgroundColor = [UIColor randomColor];
view.superview .backgroundColor=[UIColor randomColor];
}