前面在作东西的时候都用到了storyboard,在今天的代码中就纯手写代码本身用封装个Button。这个Button继承于UIView类,在封装的时候用上啦OC中的三种回调模式:目标动做回调,委托回调,Block回调。具体的内容请参考以前的博客:“Objective-C中的Block回调模式”,“Target-Action回调模式”,“Objective-C中的委托(代理)模式”。在接下来要封装的button中将要用到上面的知识点。以前在作新浪微博中的Cell的时候用到了Block回调来肯定是那个Cell上的那个Button。html
在封装Button以前呢,简单的了解一下UIView中的触摸事件:post
1.当触摸开始时会调用下面的事件atom
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)eventspa
2.当触摸取消时会调用下面的事件3d
-(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event代理
3.当触摸结束时会调用下面的事件日志
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)eventcode
4.当触摸移动时会调用下面的事件orm
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)eventhtm
因此在封装本身的button是咱们会用上上面的方法,首先新建一个ViewController, 而后把咱们新建的ViewController在AppDelegate.m中设置成咱们的根视图,咱们关于Button的初始化和配置都写在ViewController中的ViewDidLoad中代码以下:
1 MyViewController *myViewController = [[MyViewController alloc] init]; 2 self.window.rootViewController = myViewController;
1、目标动做回调:
首先新建一个MyButton类,MyButton类继承于UIView, 咱们就在MyButton类中自定义咱们的button.下面要为自定义Button添加目标动做回调接口,步骤以下:
1.在MyButton.h中声明目标动做注册方法:
//TargetAction回调 -(void)addTarget:target action:(SEL)action;
2.在MyButton.m中进行实现:
1 //延展 2 @interface MyButton() 3 4 @property (nonatomic,weak) id target; 5 @property (nonatomic, assign) SEL action; 6 7 @end 8 9 10 //实现 11 @implementation MyButton 12 //目标动做回调 13 -(void)addTarget:(id)target action:(SEL)action 14 { 15 self.target = target; 16 self.action = action; 17 }
3.经过target来执行action方法,触摸完成的事件中让target执行action方法,执行以前要判断一下触摸的释放点是否在按钮的区域内,代码以下:
1 //当button点击结束时,若是结束点在button区域中执行action方法 2 -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 3 { 4 //获取触摸对象 5 UITouch *touche = [touches anyObject]; 6 //获取touche的位置 7 CGPoint point = [touche locationInView:self]; 8 9 //判断点是否在button中 10 if (CGRectContainsPoint(self.bounds, point)) 11 { 12 //执行action 13 [self.target performSelector:self.action withObject:self]; 14 } 15 16 }
4.在MyViewController中进行button的初始化,并注册目标方法回调,当点击button时,咱们MyViewController中的tapButton方法就会被执行:
1 //在v2中添加一个button 2 MyButton *button = [[MyButton alloc] initWithFrame:CGRectMake(10, 10, 44, 44)]; 3 4 button.backgroundColor = [UIColor blackColor]; 5 6 //注册回调 7 [button addTarget:self action:@selector(tapButton)];
2、委托回调
1.在上面的基础上添加上委托回调,经过委托回调添加按钮是否可用,按钮将要点击和按钮点击后的事件,首先咱们得有协议来声明这三个方法。协议咱们就不新建文件了,下面的协议是添加在MyButton.h中的,协议定义以下:
1 //定义MyButton要实现的协议, 用于委托回调 2 @protocol MyButtonDelegete <NSObject> 3 4 //可选择的实现 5 @optional 6 7 //当button将要点击时调用 8 -(void) myButtonWillTap:(MyButton *) sender; 9 10 //当button点击后作的事情 11 -(void) myButtonDidTap: (MyButton *) sender; 12 13 //判断button是否能够被点击 14 -(BOOL) myButtonShouldTap: (MyButton *) sender; 15 16 @end
2.在MyButton.h中添加delegate属性,为了不强引用循环,定义为weak类型,用于回调的注册:
//委托回调接口 @property (nonatomic, weak) id <MyButtonDelegete> delegate;
3.在MyButton.m中当开始点击按钮时作一下处理,首先得判断delegate对象是否实现了协议中的方法若是实现了就经过delegate回调,若是没实现就不调用
2 -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 3 { 4 5 //判断myButtonShouldTap是否在degate中实现啦:委托回调 6 if ([self.delegate respondsToSelector:@selector(myButtonShouldTap:)]) 7 { 8 //若是实现了,就获取button的状态 9 myButtonState = [self.delegate myButtonShouldTap:self]; 10 11 } 12 13 //根据按钮的状态来作处理 14 if (myButtonState) 15 { 16 //若是myButtonWillTap被实现啦,此时咱们就实现myButtonWillTapf方法 17 if ([self.delegate respondsToSelector:@selector(myButtonWillTap:)]) 18 { 19 [self.delegate myButtonWillTap:self]; 20 } 21 } 22 }
4.在touchesEnded中相应的位置添加以下代码去执行按钮点击时要回调的方法:
1 //点击结束要调用myButtonDidTap 委托回调 2 if ([self.delegate respondsToSelector:@selector(myButtonDidTap:)]) 3 { 4 [self.delegate myButtonDidTap:self]; 5 }
五、在MyViewController.m中注册委托回调
1 //注册委托回调 2 button.delegate = self;
六、MyViewController要实现MyButtonDelegate,并实现相应的方法
1 //实现button委托回调的方法myButtonShouldTap:设置button是否好用 2 -(BOOL) myButtonShouldTap:(MyButton *)sender 3 { 4 NSLog(@"我是Delegate:should方法"); 5 return YES; 6 } 7 8 //实现按钮将要点击的方法 9 -(void)myButtonWillTap:(MyButton *)sender 10 { 11 NSLog(@"我是Delegate: will方法"); 12 } 13 14 //实现按钮点击完要回调的方法 15 -(void) myButtonDidTap:(MyButton *)sender 16 { 17 NSLog(@"我是Delegate: Did"); 18 }
三.Block回调
一、为咱们的按钮添加Block回调(把上面的委托回调改为Block回调),和以前微博中的Cell的Block回调相似,首先在MyButton.h中声明咱们要用的Block类型,而后提供Block的set方法:
//button中使用Block回调,定义Block类型 @class MyButton; typedef void (^ButtonWillAndDidBlock) (MyButton *sender); typedef BOOL (^ButtonShouldBlock) (MyButton *sender); //接受block的方法 -(void)setButtonShouldBlock: (ButtonShouldBlock) block; -(void)setButtonWillBlock: (ButtonWillAndDidBlock) block; -(void)setButtonDidBlock:(ButtonWillAndDidBlock) block;
2.在MyButton.m中的延展中添加相应的属性来接受Controller中传过来的Block
1 //接受block块 2 @property (nonatomic, strong) ButtonWillAndDidBlock willBlock; 3 @property (nonatomic, strong) ButtonWillAndDidBlock didBlock; 4 @property (nonatomic, strong) ButtonShouldBlock shouldBlock;
3.实现setter方法
1 //实现block回调的方法 2 -(void)setButtonWillBlock:(ButtonWillAndDidBlock)block 3 { 4 self.willBlock = block; 5 } 6 7 -(void)setButtonDidBlock:(ButtonWillAndDidBlock)block 8 { 9 self.didBlock = block; 10 } 11 12 -(void) setButtonShouldBlock:(ButtonShouldBlock)block 13 { 14 self.shouldBlock = block; 15 }
4.在MyButton.m中有委托调用的地方加入相应的Block回调,添加的代码以下:
1 //block回调 2 if (self.shouldBlock) { 3 //block回调获取按钮状态 4 myButtonState = self.shouldBlock(self); 5 } 6 7 8 //block回调实现willTap 9 if (self.willBlock) 10 { 11 self.willBlock(self); 12 } 13 14 15 //block回调 16 if (self.didBlock) { 17 self.didBlock(self); 18 }
五、在MyViewController中调用Button中的setter方法传入相应的block:
1 2 //实现button的block回调 3 [button setButtonShouldBlock:^BOOL(MyButton *sender) { 4 NSLog(@"我是Block: should方法\n\n"); 5 return YES; 6 }]; 7 8 [button setButtonWillBlock:^(MyButton *sender) { 9 NSLog(@"我是Block: Will方法\n\n"); 10 }]; 11 12 [button setButtonDidBlock:^(MyButton *sender) { 13 NSLog(@"我是Blcok: Did方法\n\n"); 14 }]; 15 16 17 [self.view addSubview:button];
通过上面的代码咱们的button就拥有三种回调模式了,下面是点击button控制台输出的日志: