最近在学习Swift ,发现青玉伏案大神早期用OC写的一篇博客--IOS开发之自定义Button(集成三种回调模式)  很适合用来熟悉Swift的回调方式,于是我就用Swift翻版了一下,具体实现原理就不多说了,主要贴上Swift的代码给大家看看。由于刚开始了解Swift,有使用不恰当的地方请轻拍。。。。

上代码:

1、新建一个xib,拖一个UIView到界面上,绑定上自定义的UIView类,拖一个UILabel到view上,写上Button假装是个UIButton;并将label拖到代码当中

2、我这里回调三种Button点击事件,TouchDown、TouchUpInside、TouchUpOutside

A、首先是Target:

a、首先声明一个枚举来设定点击类型

    enum MyControlEvents{
case TouchUpInside
case TouchUpOutside
case TouchDown
}

b、设置Target、action和Event三个属性

    //声明三个属性、添加一个addTarget方法,注意Target和delegate一样要用weak修饰
weak var target:AnyObject?
var action:Selector?
var controlEvents:MyControlEvents? func addTarget(target:AnyObject!, action: Selector!, forMyControlEvents controlEvents: MyControlEvents! ){
self.target = target
self.action = action
self.controlEvents = controlEvents
}

c、在touch事件的代理里面实现Target方法、并把label的颜色改改,这样才像button,我把代理方法写在了extension延展里面,因为我见苹果都这样

extension MyViewButton{

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {

        self.titleLabel.textColor = UIColor.lightGrayColor()

        if self.controlEvents == MyControlEvents.TouchDown{
self.target?.performSelector(self.action!, withObject: self)
}
} override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) { self.titleLabel.textColor = UIColor.blueColor() //let point:CGPoint = (touches as NSSet).anyObject()!.locationInView(self)、下面方法的合体
let view = (touches as NSSet).anyObject()
let point:CGPoint = view!.locationInView(self)
//判断Target类型和触摸点移出情况相匹配时执行target方法
if CGRectContainsPoint(self.bounds, point) && self.controlEvents == MyControlEvents.TouchUpInside{
self.target?.performSelector(self.action!, withObject: self)
}else if !CGRectContainsPoint(self.bounds, point) && self.controlEvents == MyControlEvents.TouchUpOutside{
self.target?.performSelector(self.action!, withObject: self)
}
}

d、在VC中实现,选择不同的点击类型即可监控不同的点击事件啦

    class ViewController: UIViewController , MyViewButtonDelegate {

    var myButton:MyViewButton?

    override func viewDidLoad() {
super.viewDidLoad()
//从xib中加载我们自定义的view,我的xib叫做“View”
let bundel:NSBundle = NSBundle.mainBundle()
let views:Array = bundel.loadNibNamed("View", owner: nil, options: nil) self.myButton = views.last as? MyViewButton
self.myButton?.frame = CGRectMake(80, 200, 200, 100) self.view.addSubview(self.myButton!) self.myButton?.addTarget(self, action: Selector!("didTapButton:"), forMyControlEvents: MyControlEvents.TouchUpInside)
}

最后 实现点击方法即可

func didTapButton(button:MyViewButton){
print("VC点击了按钮---点击类型是\(button.controlEvents)")
}

 B、协议

1、声明一个protocol,里面有三个可选实现的方法,并把自身当做参数带出去

    objc protocol MyViewButtonDelegate:NSObjectProtocol{
optional func didTouchMyButton(button:MyViewButton)
optional func didTouchUpInsideButton(button:MyViewButton)
optional func didTouchUpOutsideButton(button:MyViewButton)
}

2、声明一个delegate属性,同样是弱指针引用

    weak var delegate:MyViewButtonDelegate!

3、同样在touch事件中实现

    extension MyViewButton{
//调用协议方法时判断一下delegate和协议方法是否存在
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) { self.titleLabel.textColor = UIColor.lightGrayColor()
if self.delegate != nil && self.delegate!.respondsToSelector("didTouchMyButton:"){
self.delegate?.didTouchMyButton!(self)
}
} override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) { self.titleLabel.textColor = UIColor.blueColor() //let point:CGPoint = (touches as NSSet).anyObject()!.locationInView(self)
let view = (touches as NSSet).anyObject()
let point:CGPoint = view!.locationInView(self) if CGRectContainsPoint(self.bounds, point){
if self.delegate != nil && self.delegate!.respondsToSelector("didTouchUpInsideButton:"){
self.delegate?.didTouchUpInsideButton!(self)
}
}else{
if self.delegate != nil && self.delegate!.respondsToSelector("didTouchUpOutsideButton:"){
self.delegate?.didTouchUpOutsideButton!(self)
}
}
}
}

4、在VC中实现即可

    class ViewController: UIViewController , MyViewButtonDelegate {
override func viewDidLoad() {
super.viewDidLoad() let bundel:NSBundle = NSBundle.mainBundle()
let views:Array = bundel.loadNibNamed("View", owner: nil, options: nil) self.myButton = views.last as? MyViewButton
self.myButton?.frame = CGRectMake(80, 200, 200, 100) self.view.addSubview(self.myButton!)
//设置button的代理
self.myButton!.delegate = self
} extension ViewController{
//实现代理方法
func didTouchMyButton(button: MyViewButton) {
print("delegate--VC点击了button")
}
func didTouchUpInsideButton(button: MyViewButton) {
print("delegate--TouchUpInside")
} func didTouchUpOutsideButton(button: MyViewButton) {
print("delegate--TouchUpOutside")
} }

 C、闭包(block)

1、首先在自定义view里实现,相当于typedef一个block类型

typealias MyBlock = (button:MyViewButton)->Void

2、声明三个block属性,并且声明三个给block赋值方法

    var TouchBlockHandel:MyBlock?
var TouchUpInsideBlockHandel:MyBlock?
var TouchUpOutsideBlockHandel:MyBlock?
//也可以不写方法直接属性赋值
func setMyTouchBlock(block:MyBlock){
self.TouchBlockHandel = block
}
func setMyTouchUpInsideBlock(block:MyBlock){
self.TouchUpInsideBlockHandel = block
}
func setMyTouchUpOutsideBlock(block:MyBlock){
self.TouchUpOutsideBlockHandel = block
}

3、在touch事件中实现block

    extension MyViewButton{

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
self.titleLabel.textColor = UIColor.lightGrayColor()
self.TouchBlockHandel!(button: self)
} override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) { self.titleLabel.textColor = UIColor.blueColor() //let point:CGPoint = (touches as NSSet).anyObject()!.locationInView(self)
let view = (touches as NSSet).anyObject()
let point:CGPoint = view!.locationInView(self) if CGRectContainsPoint(self.bounds, point){
self.TouchUpInsideBlockHandel!(button: self)
}else{
self.TouchUpOutsideBlockHandel!(button: self)
}
}

4、同样在VC中给三个block赋值即可

    class ViewController: UIViewController , MyViewButtonDelegate {

    var myButton:MyViewButton?

    override func viewDidLoad() {
super.viewDidLoad() let bundel:NSBundle = NSBundle.mainBundle()
let views:Array = bundel.loadNibNamed("View", owner: nil, options: nil) self.myButton = views.last as? MyViewButton
self.myButton?.frame = CGRectMake(80, 200, 200, 100) self.view.addSubview(self.myButton!) self.myButton?.setMyTouchBlock({ (button:MyViewButton) -> Void in
print("block--VC点击了button")
})
self.myButton?.setMyTouchUpInsideBlock({ (button:MyViewButton) -> Void in
print("block--VCTouchUpInside")
})
self.myButton?.setMyTouchUpOutsideBlock({ (button:MyViewButton) -> Void in
print("block--VCTouchUpOutside")
})
} }

最后来看看三个方法写在一起的打印结果。就添加了一个target监控TouchUpInside。总体来说和OC逻辑没有任何变化,只是语法上有所不同,block还是好用

好了,这样就结束了,今天下雪了,大家注意保暖!

iOS_Swift初识之使用三种回调方式自定义Button的更多相关文章

  1. 通过三个DEMO学会SignalR的三种实现方式

    一.理解SignalR ASP .NET SignalR 是一个ASP .NET 下的类库,可以在ASP .NET 的Web项目中实现实时通信(即:客户端(Web页面)和服务器端可以互相实时的通知消息 ...

  2. Service组件 总结 + 绑定理Service三种实现方式 Messager + Binder + AIDL

    在Android中进程按优先级可以分为五类,优先级从高到低排列: - 前台进程 该进程包含正在与用户进行交互的界面组件,比如一个Activity - 可视进程 该进程中的组件虽然没有和用户交互,但是仍 ...

  3. Android平台中实现对XML的三种解析方式

    本文介绍在Android平台中实现对XML的三种解析方式. XML在各种开发中都广泛应用,Android也不例外.作为承载数据的一个重要角色,如何读写XML成为Android开发中一项重要的技能. 在 ...

  4. Spring IOC以及三种注入方式

    IOC是spring的最基础部分,也是核心模块,Spring的其他组件模块和应用开发都是以它为基础的.IOC把spring的面向接口编程和松耦合的思想体现的淋漓尽致. IOC概念 IOC(Invers ...

  5. C# 三种打印方式含代码

    一:C#代码直接打印pdf文件(打印质保书pdf文件) 引用: 代码注释很详细了. private void btn_pdf_Click(object sender, RoutedEventArgs ...

  6. SignalR代理对象异常:Uncaught TypeError: Cannot read property 'client' of undefined 推出的结论 SignalR 简单示例 通过三个DEMO学会SignalR的三种实现方式 SignalR推送框架两个项目永久连接通讯使用 SignalR 集线器简单实例2 用SignalR创建实时永久长连接异步网络应用程序

    SignalR代理对象异常:Uncaught TypeError: Cannot read property 'client' of undefined 推出的结论   异常汇总:http://www ...

  7. python笔记-20 django进阶 (model与form、modelform对比,三种ajax方式的对比,随机验证码,kindeditor)

    一.model深入 1.model的功能 1.1 创建数据库表 1.2 操作数据库表 1.3 数据库的增删改查操作 2.创建数据库表的单表操作 2.1 定义表对象 class xxx(models.M ...

  8. 延迟加载(Lazyload)三种实现方式

    定义:延迟加载也称为惰性加载,即在长网页中延迟加载图像.用户滚动到它们之前,视口外的图像不会加载.这与图像预加载相反,在长网页上使用延迟加载将使网页加载更快.在某些情况下,它还可以帮助减少服务器负载. ...

  9. 2019年6月14日 Web框架之Django_07 进阶操作(MTV与MVC、多对多表三种创建方式、前后端传输数据编码格式contentType、ajax、自定义分页器)

    摘要 MTV与MVC 多对多表三种创建方式 ajax ,前后端传输数据编码格式contentType 批量插入数据和自定义分页器 一.MVC与MTV MVC(Model View Controller ...

随机推荐

  1. CSS之立方体绘画步骤

    附上总的代码: <!DOCTYPE html><html><head> <title>立方体</title> <meta charse ...

  2. centos7安装nginx

    一般我们都需要先装pcre, zlib,前者为了重写rewrite,后者为了gzip压缩. 一:安装 pcre 1.下载地址:百度云盘 http://pan.baidu.com/s/1dFusO3v ...

  3. JPA使用入门

    JPA能干什么?我在前面一遍文章<初步了解JPA>基本描述了.不过你不需要点击回去再看.这里简单的再提一下JPA的功能,就是:(1)实现“对象-关系”映射:(2)对象持久化到数据库:(3) ...

  4. CheckBoxList控件获取多选择,需要遍历

    CheckBoxList控件获取多选择,需要遍历,环境:vs2008 在页面上添加CheckBoxList控件,输入项值 a,b,c,d.然后添加按钮 Button2确定,如何获取CheckBoxLi ...

  5. C#事件支持发布者/订阅者模式(观察者模式)

    C#事件支持发布者/订阅者模式,发布者将事件通知给订阅者,而订阅者在事件发生时调用已经注册好的事件处理函数.        public delegate void delUpdate();  //委 ...

  6. 2016 - 1 - 25 第三方网络框架 AFN的简单使用

    AFNetworking 底层是对NSURlSession 和对 NSURLConnect 的包装 1.具体使用方法可以参照github上的主页面,在这里只是举一个文件上传的简单列子 - (void) ...

  7. ThinkPHP_基础(1)目录结构

    (说明:文中的颜色一一对应) 目录结构 www WEB部署目录(或者子目录) ├─index.php 入口文件 ├─README.md README文件 ├─composer.json Compose ...

  8. 【Mocha.js 101】钩子函数

    前情提要 在上一篇文章<[Mocha.js 101]同步.异步与 Promise>中,我们学会了如何对同步方法.异步回调方法以及 Promise 进行测试. 在本篇文章中,我们将了解到 M ...

  9. 基于数据库MySQL的简易学生信息管理系统

    通过这几天学习Mysql数据库,对其也有了基本的了解,为了加深印象,于是就写了一个最简易的学生信息管理系统. 一:基本要求 1.通过已知用户名和密码进行登录: 2.可以显示菜单: 3.可以随时插入学生 ...

  10. Linux学习之路—磁盘分区

    1.各硬件设备在Linux中的文件名 在Linux系统中,每个设备都被当做一个文件来对待,同时在Linux系统中,几乎所有的硬件设备文件都在/dev这个目录中. 设备 设备在Linux内的文件名 ID ...