最近在学习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. String使用机制及string.equals()和==的区别(转)

    http://904582819.blog.163.com/blog/static/11159282020127794456840/ equals方法和==的区别   首先大家知道,String既可以 ...

  2. mvc 传递匿名对象

    Controller代码: public ActionResult TupleTest() { LinqDBEntities db = new LinqDBEntities(); dynamic da ...

  3. GCHandler的使用

    众所周知,我们在使用c#托管代码时,内存地址和GC回收那不是我们关心的,CLR已经给我们暗箱操作. 但是如果我们在c#中调用了一个非托管代码,比如vc的DLL,而且他有个回调函数,需要引用c#中的某个 ...

  4. linux下进程突然断掉后的日志查询

    最近写了一个实现监控的服务,可某天去看的时候进程突然木有了,这就捉急了,好好的是啥原因了呢?不会有人不小心把偶的进程关掉了把! 后发现一个linux日志文件:/var/log/messages 打开文 ...

  5. Windows多网卡上网设置

    http://blog.tianya.cn/blogger/post_show.asp?BlogID=1566293&PostID=12984307

  6. html+css知识点总结(田彦霞)

    html部分 html头部声明 DOCTYPE是document type(文档类型)的简写,用来说明你用的XHTML或者HTML是什么版本.DOCTYPE声明必须放在每一个XHTML文档最顶部,在所 ...

  7. 数据结构《20》----Immutable stack

    有趣的函数式数据结构<一>----不可变栈 什么是不可变?往栈中插入一个元素,原来的栈保持不变,返回一个新的栈(已插入新的元素). push, pop,getMax 等操作都要求在 常数时 ...

  8. pip和requests模块的安装

    1.配置python的环境变量 在path中加入pyhton的环境变量,如我的是E:\Python27 2. 如果没有pip,一个帮助软件管理的东东(现在的版本一般有,若有跳到3) 去https:// ...

  9. WCF 部署在Windows 2012 IIS上各种报错的解决方法

    1.由于扩展配置问题而无法提供您请求的页面.如果该页面是脚本 ,请添加处理程序.如果勇载文件,请添加 MIME 映射. 以管理员身份,在cmd中运行C:\Windows\Microsoft.NET\F ...

  10. 购物车数字加减按钮HTML+CSS+JS(有需要嫌麻烦的小伙伴拿走不谢)

    之前在写详情页的时候,如下图 因为自己嫌麻烦,就去看其他网站是怎么写的,想直接拿来用,后来看来看去觉得写得很麻烦,于是最后还是决定自己写,附上HTML+CSS+JS代码,一条龙一站式贴心服务2333 ...