Swift超基础语法(协议与代理篇)

代理设计模式是开发中比较常见的设计模式之一,那么在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方法,表示:如果人不找黄牛买火车票,黄牛就会饿死,诶?我为什么要写这一句...无视,无视
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,271评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,725评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,252评论 0 328
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,634评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,549评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,985评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,471评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,128评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,257评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,233评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,235评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,940评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,528评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,623评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,858评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,245评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,790评论 2 339

推荐阅读更多精彩内容