这两天看了一下Swift的协议代理,大体思路和OC没什么区别,但是按照官方的书本写出的协议代理,发现会有内存泄露问题,找了半天没有发现问题,突然想起看系统类的协议代理的写法,瞬间发现了问题,不多废话了,下面是代码.
我建了一个single View application,为了验证内存泄露,我保留了xcode所给的viewController.swift,在storyboard中viewController前添加了一个navigationController,并且自己建了两个视图控制器: VC1.swift 和 VC2.swift,由viewController 跳转至 VC1,在VC1中设置delegate,再跳转到VC2,让VC2改变VC1的背景颜色,然后一直返回到viewController,看VC1 和 VC2 是否释放了内存;
下面是我的viewController里的代码:
// // ViewController.swift // protocolTest // // Created by XXX on 16/8/26. // Copyright © 2015年 V1. All rights reserved. // import UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() self.title = "viewController" //实例化一个button,添加点击事件 let button = UIButton(type: UIButtonType.Custom) button.backgroundColor = UIColor.redColor() button.setTitle("点击跳转到VC1",forState: UIControlState.Normal) button.frame = CGRectMake(100,100,150,100) button.addTarget(self,action: "buttonClicked",forControlEvents: UIControlEvents.TouchUpInside) self.view.addSubview(button) } //跳转到VC1 func buttonClicked(){ let vc_1 = VC1() self.navigationController?.pushViewController(vc_1,animated: true) } }
这下面是VC1 中的代码:
// // VC1.swift // protocolTest // // Created by XXX on 16/8/26. // Copyright © 2015年 V1. All rights reserved. // import UIKit // VC1 遵守changeColor协议,并且实现协议中的方法 class VC1: UIViewController,changeColor{ var vc_2: VC2? //定义一个VC2变量 override func viewDidLoad() { super.viewDidLoad() self.view.backgroundColor = UIColor.orangeColor() self.title = "VC1" //实例化VC2,并且设置delegate vc_2 = VC2() vc_2?.delegate = self let button = UIButton(type: UIButtonType.Custom) button.backgroundColor = UIColor.whiteColor() button.setTitle("点击跳转到VC2",forState: UIControlState.Normal) button.setTitleColor(UIColor.blackColor(),action: "VC1buttonClicked",forControlEvents: UIControlEvents.TouchUpInside) self.view.addSubview(button) } //跳转到VC2 func VC1buttonClicked(){ self.navigationController?.pushViewController(vc_2!,animated: true) } //实现协议中的方法 func changeColorWithColor(color color: UIColor) { self.view.backgroundColor = color } deinit{ print("vc_1 的内存已释放 !") } }
下面是我的VC2中的代码:
// // VC2.swift // protocolTest // // Created by XXXX on 16/8/26. // Copyright © 2015年 V1. All rights reserved. // import UIKit //声明一个协议,让其继承(我也不知道该不该叫继承,然而在这里并不重要) NSObjectProtocol,只有这样才能在设置代理的时候前面添加weak protocol changeColor: NSObjectProtocol { func changeColorWithColor(color color: UIColor) } class VC2: UIViewController { //注意这里: changeColor为协议名,delegate前面必须有weak修饰,如果没有weak修饰就会造成内存泄露,而可以加weak的前提是,这个协议必须继承 NSObjectProtocol,这是我试验出来的,目前来看,应该是这样的 weak var delegate: changeColor? override func viewDidLoad() { super.viewDidLoad() self.view.backgroundColor = UIColor.whiteColor() self.title = "VC2" let button = UIButton(type: UIButtonType.Custom) button.backgroundColor = UIColor.redColor() button.setTitle("点击改变VC1的背景颜色",200,forControlEvents: UIControlEvents.TouchUpInside) self.view.addSubview(button) } func VC1buttonClicked(){ //使用代理调用协议声明并且VC1已经实现的方法 self.delegate?.changeColorWithColor(color: UIColor.cyanColor()) } deinit{ print("vc_2的内存已经释放 !") } }
下面是返回至viewController后的打印信息:
/* vc_1 的内存已释放 ! vc_2的内存已释放 ! */
最重要的代码片段为:
//注意这里: changeColor为协议名,应该是这样的
weak var delegate: changeColor?