前面在做东西的时候都用到了storyboard,在今天的代码中就纯手写代码自己用封装个Button。这个Button继承于UIView类,在封装的时候用上啦OC中的三种回调模式:目标动作回调,委托回调,Block回调。具体的内容请参考之前的博客:“Objective-C中的Block回调模式”,“Target-Action回调模式”,“Objective-C中的委托(代理)模式”。在接下来要封装的button中将要用到上面的知识点。之前在做新浪微博中的Cell的时候用到了Block回调来确定是那个Cell上的那个Button。

  在封装Button之前呢,简单的了解一下UIView中的触摸事件:

    1.当触摸开始时会调用下面的事件

      -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

    2.当触摸取消时会调用下面的事件

      -(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event

       3.当触摸结束时会调用下面的事件

      -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event

    4.当触摸移动时会调用下面的事件

      -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event

  所以在封装自己的button是我们会用上上面的方法,首先新建一个ViewController, 然后把我们新建的ViewController在AppDelegate.m中设置成我们的根视图,我们关于Button的初始化和配置都写在ViewController中的ViewDidLoad中代码如下:

1    MyViewController *myViewController = [[MyViewController alloc] init];
2    self.window.rootViewController = myViewController;

  一、目标动作回调:

    首先新建一个MyButton类,MyButton类继承于UIView, 我们就在MyButton类中自定义我们的button.下面要为自定义Button添加目标动作回调接口,步骤如下:

      1.在MyButton.h中声明目标动作注册方法:

//TargetAction回调
-(void)addTarget:target action:(SEL)action;

    2.在MyButton.m中进行实现:

//延展
@interface MyButton()@property (nonatomic,weak) id target;
@property (nonatomic, assign) SEL action;@end//实现
@implementation MyButton
//目标动作回调
-(void)addTarget:(id)target action:(SEL)action
{self.target = target;self.action = action;
}

  

    3.通过target来执行action方法,触摸完成的事件中让target执行action方法,执行之前要判断一下触摸的释放点是否在按钮的区域内,代码如下:

//当button点击结束时,如果结束点在button区域中执行action方法
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{//获取触摸对象UITouch *touche = [touches anyObject];//获取touche的位置CGPoint point = [touche locationInView:self];//判断点是否在button中if (CGRectContainsPoint(self.bounds, point)){//执行action[self.target performSelector:self.action withObject:self];  }}

    4.在MyViewController中进行button的初始化,并注册目标方法回调,当点击button时,我们MyViewController中的tapButton方法就会被执行:

//在v2中添加一个buttonMyButton *button = [[MyButton alloc] initWithFrame:CGRectMake(10, 10, 44, 44)];button.backgroundColor = [UIColor blackColor];//注册回调[button addTarget:self action:@selector(tapButton)];

  二、委托回调 

   1.在上面的基础上添加上委托回调,通过委托回调添加按钮是否可用,按钮将要点击和按钮点击后的事件,首先我们得有协议来声明这三个方法。协议我们就不新建文件了,下面的协议是添加在MyButton.h中的,协议定义如下:

//定义MyButton要实现的协议, 用于委托回调
@protocol MyButtonDelegete <NSObject>//可选择的实现
@optional//当button将要点击时调用
-(void) myButtonWillTap:(MyButton *) sender;//当button点击后做的事情
-(void) myButtonDidTap: (MyButton *) sender;//判断button是否可以被点击
-(BOOL) myButtonShouldTap: (MyButton *) sender;@end

    2.在MyButton.h中添加delegate属性,为了避免强引用循环,定义为weak类型,用于回调的注册:

//委托回调接口
@property (nonatomic, weak) id <MyButtonDelegete> delegate;

    3.在MyButton.m中当开始点击按钮时做一下处理,首先得判断delegate对象是否实现了协议中的方法如果实现了就通过delegate回调,如果没实现就不调用

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{//判断myButtonShouldTap是否在degate中实现啦:委托回调if ([self.delegate respondsToSelector:@selector(myButtonShouldTap:)]){//如果实现了,就获取button的状态myButtonState = [self.delegate myButtonShouldTap:self];} //根据按钮的状态来做处理if (myButtonState){//如果myButtonWillTap被实现啦,此时我们就实现myButtonWillTapf方法if ([self.delegate respondsToSelector:@selector(myButtonWillTap:)]){[self.delegate myButtonWillTap:self];}}
}

    4.在touchesEnded中相应的位置添加如下代码去执行按钮点击时要回调的方法:

1         //点击结束要调用myButtonDidTap  委托回调
2         if ([self.delegate respondsToSelector:@selector(myButtonDidTap:)])
3         {
4             [self.delegate myButtonDidTap:self];
5         }

    5、在MyViewController.m中注册委托回调

1     //注册委托回调
2     button.delegate = self;

    6、MyViewController要实现MyButtonDelegate,并实现相应的方法

//实现button委托回调的方法myButtonShouldTap:设置button是否好用
-(BOOL) myButtonShouldTap:(MyButton *)sender
{NSLog(@"我是Delegate:should方法");return YES;
}//实现按钮将要点击的方法
-(void)myButtonWillTap:(MyButton *)sender
{NSLog(@"我是Delegate: will方法");
}//实现按钮点击完要回调的方法
-(void) myButtonDidTap:(MyButton *)sender
{NSLog(@"我是Delegate: Did");
}

  三.Block回调

    1、为我们的按钮添加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方法

//实现block回调的方法
-(void)setButtonWillBlock:(ButtonWillAndDidBlock)block
{self.willBlock = block;
}-(void)setButtonDidBlock:(ButtonWillAndDidBlock)block
{self.didBlock = block;
}-(void) setButtonShouldBlock:(ButtonShouldBlock)block
{self.shouldBlock = block;
}

    4.在MyButton.m中有委托调用的地方加入相应的Block回调,添加的代码如下:

//block回调if (self.shouldBlock) {//block回调获取按钮状态myButtonState = self.shouldBlock(self);}//block回调实现willTapif (self.willBlock){self.willBlock(self);}//block回调if (self.didBlock) {self.didBlock(self);}

   5、在MyViewController中调用Button中的setter方法传入相应的block:

//实现button的block回调[button setButtonShouldBlock:^BOOL(MyButton *sender) {NSLog(@"我是Block: should方法\n\n");return YES;}];[button setButtonWillBlock:^(MyButton *sender) {NSLog(@"我是Block: Will方法\n\n");}];[button setButtonDidBlock:^(MyButton *sender) {NSLog(@"我是Blcok: Did方法\n\n");}];[self.view addSubview:button];

 经过上面的代码我们的button就拥有三种回调模式了,下面是点击button控制台输出的日志:

IOS开发之自定义Button(集成三种回调模式)相关推荐

  1. 自定义View的三种实现方式及自定义属性使用介绍

    自定义View的三种实现方式及自定义属性使用介绍 一 前言 二 三种自定义控件的方法 2.1 组合控件 2.2 继承控件 2.2.1 继承View类系统控件 2.2.2 继承ViewGroup类系统控 ...

  2. (OPC Client .NET 开发类库)网上很多网友都有提过,.NET开发OPC Client不外乎下面三种方法...

    1. 背景 OPC Data Access 规范是基于COM/DCOM定义的,因此大多数的OPC DA Server和client都是基于C++开发的,因为C++对COM/DCOM有最好的支持.现在, ...

  3. 最直白理解NFC开发的三种工作模式

    刚开始开发NFC时,说的三种模式:说的感觉都是些专业术语.看的不是很明白,以下是最直白的NFC三种模式的介绍. 1.NFC的工作模式 NFC支持如下3种工作模式:读卡器模式(Reader/writer ...

  4. iOS开发之自定义View的一些坑

    我们做几个简单的例子哈 自定义一个View View的m文件中有代码如下: @implementation BMView- (instancetype)init {if (self = [super ...

  5. python编程模式是什么_python 开发的三种运行模式详细介绍

    Python 三种运行模式 Python作为一门脚本语言,使用的范围很广.有的同学用来算法开发,有的用来验证逻辑,还有的作为胶水语言,用它来粘合整个系统的流程.不管怎么说,怎么使用python既取决于 ...

  6. Kotlin实战练习——自定义圆形图片三种实现方式

    Kotlin实战练习--自定义圆形图片三种实现方式 前言 如今Kotlin越来越重要,本人也开始了Kotlin的学习.为了检测学习效果,加深学习印象,同时回顾一下以前的一些知识点,决定从写一个自定义圆 ...

  7. hadoop离线阶段(第十三节)数据仓库、hive简介、hive安装和hive的三种交互模式

    目录 数据仓库 数据仓库的基本概念 数据仓库的主要特征 数据仓库与数据库区别 数据仓库分层架构 数据仓库元数据管理 Hive简介 什么是Hive Hive的特点 Hive架构 Hive与Hadoop的 ...

  8. 【云计算学习教程】IaaS、PaaS和SaaS:云计算的三种服务模式(精讲)

    文章目录 云计算IaaS服务模式精讲 第一层(云管理器) 第二层(集群管理器) 第三层(计算机管理器) 云计算PaaS服务模式精讲 1)半平台 PaaS 2)全平台 PaaS 云计算SaaS服务模式精 ...

  9. 华为云电脑.模式_今晚0元学华为云计算HCIA课程!快上车,提前了解云计算三种服务模式...

    点上方蓝字关注,每天都有新收获! 学网络,就在IE-LAB 国内高端网络工程师培养基地 今晚0元学华为云计算HCIA课程! 快上车啦 今晚7:30--9:30 扫码火速报名 云计算是一种全新的商业模式 ...

最新文章

  1. java Reference
  2. 【普及组模拟赛】家族
  3. vscode终端无法输入
  4. Flex AIR 文件对象操作
  5. 新人起步,扬帆起航!
  6. golang编译时报错:Get “https://proxy.golang.org/github.com/antihax/optional/@v/v1.0.0.mod“: dial tcp 172.2
  7. Go语言后端开发技术栈
  8. retainall java_瞬间教你学会使用java中list的retainAll方法
  9. python代码库-这7个开源的Python库,让你轻松代码分析
  10. 那个程序员的 Linux 常用软件清单 | Linux 工具篇
  11. matlab中字符串的大小比较,matlab中字符串的最大大小
  12. 数组,异质结构以及指针的详解
  13. 鸿蒙系统电脑适配双面打印机,win10系统实现打印机双面打印的操作方法
  14. 【随笔】写在2020除夕之夜
  15. redis学习笔记(十一)AKF、CAP理论
  16. 【C++Primer笔记】第四章 表达式
  17. 分批处理list中的数据_如何分批次处理List集合中的数据
  18. 自己定义控件事实上非常easy1/6
  19. Dell笔记本拆机加内存条
  20. 入手级仿真软件和编辑器安装(VIVADO)

热门文章

  1. 数据为什么要可视化?如何可视化?
  2. vscode插件列表及配置信息
  3. java8新特性: lambda表达式:直接获得某个list/array/对象里面的字段集合
  4. RPC框架原理及从零实现系列博客(二):11个类实现简单RPC框架
  5. [EntLib]微软企业库5.0 学习之路——第七步、Cryptographer加密模块简单分析、自定义加密接口及使用—上篇...
  6. [Modules]PrestaShop插件 模块 – 产品推荐模块 随机展示推荐产品
  7. 关于Django将数据映射到Html中的操作
  8. 一文看懂软件测试方法和规范
  9. js获取当前页面的参数,带完善~~~
  10. 某网SQL注入漏洞实战