代理设计模式是开发中比较常见的设计模式之一,那么在Swift中应该如何实现代理与协议呢?
协议(protocol)
- 协议用于定义一些函数的声明,并要求其他类来实现这个函数的具体内容,概念与OC无异,有些类似Java中的接口
- apple不建议开发者在Swift中的协议里定义"可选实现的函数",并且Swift协议中的函数默认都是必须实现的,这是为了保证Swfit这门语言的严谨性
- Swift协议中必须实现的函数如果不实现则直接编译报错(这与OC这样的弱语言不同)
定义协议的格式
编写协议的格式:
protocol 协议名字 : 基协议 { //当然也可以不遵守基协议
//方法的声明
}
例:定义一个买票的协议
protocol buyTicketProtocol {
func buyTicket() -> Void
}
Tips:
如果一个协议继承了基协议NSObjectProtocol,那么遵守这个协议的类也必须要继承NSObject这个类
遵守协议的格式
一个类若要遵守一个协议,只需要在自己所继承的父类后面写上要遵守的协议名并以逗号","隔开,如果这个类无需继承,那么直接在冒号后面写上协议的名字就好
遵守协议的格式:
class Person : NSObject,SportProtocol{}
例:定义一个会买票的黄牛类
class Tout : buyTicketProtocol { //无继承类遵守协议
func buyTicket() {
print("here's your ticket")
}
}
Tips:
Swift中的基协为NSObjectProtocol,这与OC中的基协议(NSObject)有些不同
协议的继承
- 上面有提到,当我们自定义一个协议的时候可以选择让这个协议继承自NSObjectProtocol,不单单如此,自定义的协议也可以遵守另外一个协议哦,基本格式如下:
protocol showTicketNumberProtocol { //展示票号
func showTicketNumber() -> Void
}
protocol buyTicketProtocol : showTicketNumberProtocol { //买票
func buyTicket() -> Void
}
- 如果一个类遵循了一个含有继承的协议,那么这个类就必须实现这个协议链中所有的必须实现的函数,否则编译报错
class Tout : buyTicketProtocol {
func buyTicket() {
print("here's your ticket")
}
func showTicketNumber() { //必须实现buyTicketProtocol所继承的"父"协议中的函数
print("123456")
}
}
Tips:
上面提到的"如果一个协议继承了基协议NSObjectProtocol,那么遵守这个协议的类也必须要继承NSObject这个类"
这是因为我们需要NSObject这个父类来帮我们实现NSObjectProtocol中定义的函数,否则编译器会以"没有实现NSObjectProtocol中的函数为由而报错"
协议中可选实现的函数
为了保证Swift语言的严谨性,不建议在协议中定义可选实现的函数,不过不建议不代表不能嘛,我们可以利用OC特性来实现在Swift协议中定义可选实现函数
- 创建带有OC特性的协议
@objc //表示一下代码含有OC特性
protocol showTicketNumberProtocol {
optional func showTicketNumber() -> Void //optional修饰的函数为可选择实现(或不实现)的函数
}
- 遵守带有OC特性的协议
class Tout : showTicketNumberProtocol {
//终于,下面这个函数可以不实现,并且不会报错了
@objc func showTicketNumber() { //由于showTicketNumberProtocol含有OC特性,于是这个协议中所有的函数在实现之前都要有@objc来修饰
print("123456")
}
}
Swift中的协议与代理设计模式
首先要明确,在Swift中一个协议不仅可以被类遵守,还可以被结构体/枚举来遵守,所以当我们在Swift中使用代理设计模式时,要明确的告诉编译器,我定义的这个协议是供一个class来遵守的,反例如下:
反例:书接上文的例子,托人买火车票
class Person {
weak var delegate : buyTicketProtocol? //此时会处于编译报错的状态,这是因为buyTicketProtocol这个协议并没有明确规定是由类来遵守的
}
正确的做法如下:
例:托人买火车票(协议的知识点的小综合^ ^)
//父协议
@objc //含有OC特性的代码
protocol showTicketNumberProtocol : class { //遵守class,表示这个协议由class来遵守
optional func showTicketNumber() -> Void //展示票号(可选实现)
}
//子协议
protocol buyTicketProtocol : showTicketNumberProtocol //遵守showTicketNumberProtocol,表示能实现当前协议中的函数的人,必须要能实现showTicketNumberProtocol中定义的必须实现的函数
showTicketNumberProtocol { //买票
func buyTicket() -> Void
}
//黄牛类
class Tout : buyTicketProtocol { //黄牛类,遵守协议,代表能买到票
func buyTicket() { //实现买票函数
print("here's your ticket")
}
// @objc func showTicketNumber() { //此处并没有实现展示票号的函数,不会报错
// print("123456")
// }
}
//需要买票的Person类
class Person { //定义Person类
weak var delegate : buyTicketProtocol? //定义一个代理,代理必须能买到票
}
//外部调用
//实例化对象
let p = Person() //创建一个需要买火车票的人
let t = Tout() //创建一个会买火车票的黄牛
//调用代理方法
p.delegate = t //人的代理设置为黄牛
p.delegate?.buyTicket() //黄牛买了一张火车票,控制台打印:here's your ticket
// p.delegate?.showTicketNumber!() //这个函数没有被实现,所以此处使用!会导致程序崩溃
p.delegate?.showTicketNumber?() //如果使用可选链,那么这个方法将不会执行,也不会报错
p.delegate = nil //此处会自动调用Tout的deinit方法,表示:如果人不找黄牛买火车票,黄牛就会饿死,诶?我为什么要写这一句...无视,无视