标签:ios8 swift delegation 代理 内存管理
上一话中介绍了扩展和协议的相关知识,这一话我们介绍一个很重要的概念delegation(代理),代理是协议的一个很重要的应用。我们来回顾一下代理的相关知识,它是控制器和试图通讯的关键。
那么代理是如何工作的呢
1.你需要创建一个代理协议,它描述了这个试图要帮别人做的事情。
2.在你的视图中创建一个属性,称作代理或者有时也叫数据源,这个属性的类型就是你创建的代理协议。
3.然后你使用这个属性去处理所有的代理,代理属性会去请求它所需要的数据,记得试图本身是不能拥有数据的。只要是遵循这个协议的对象都可以向这个协议中的属性设值,有了值之后我们的视图就知道该如何做了。
4.控制器首先会说它自身实现了这个协议,然后它将它自身作为代理对象
5.控制器实现所有的代理方法,这样它就遵循了协议
现在控制器已经和视图建立了连接,虽然它不知道控制它的类是什么样的,这些数据是什么,它唯一知道的是这个控制器实现了视图中的协议方法。
下面让我们回到我们的小人脸的Demo中看看如何实现上述的操作。
让faceView中的代理获得它的数据,这个数据就是它的smiliness,而HappinessViewController会成为它的控制器。
在FaceView中加入如下代码:
protocol FaceViewDataSource { func smilinessForFaceView(sender: FaceView) -> Double? }
第二步是,在我们的FaceView中我们需要有一个公开的变量:
var dataSource:FaceViewDataSource?可以看到这里把我们的协议作为了数据类型,那么如果我们想要让某个协议成为我们的代理,只需要将协议设置为类的变量的值,使用可选型是因为没有控制器去遵循我们的代理协议,那么我们的小人脸的嘴就会是一条直线不会变化,协议可以是nil,虽然通常我们不希望它是nil。
我们希望它是弱类型的:
weak var dataSource:FaceViewDataSource?
这涉及到内存管理的知识,事实上内存是被操作系统自动管理的,所以不需要担心。但是需要注意的是如果控制器把它自身当做代理,然后它把指针指向自身,不幸的是如果我们的控制器在视图层上已经有一个FaceView的指针了,因为它有一个连接到FaceView的outlet,这样两个对象就互相指向了对方。这种情况下它们就会一直在内存中互相引用对方,内存中出现这样的循环是很可怕的,因为控制器和视图都无法释放内存,它们会永远呆在内存中,所以使用weak关键字意思是无论它指向了什么对象,它都不该留在内存中。通常我们不怎么使用weak,但是在IBOutlet中weak被大量使用,代理的使用是另一个应用到weak的地方。这样我们有一个代理的时候我们始终需要一个weak类型的变量。
你会发现上面这句话报错了,提示我们weak只能用在类中,虽然我们的代理是一个协议,但是前几话中讲到了你可以通过如下写法把它设定为只能被类遵循:
protocol FaceViewDataSource:class { func smilinessForFaceView(sender: FaceView) -> Double? }
之前smiliness的值是写死的,现在我们希望smiliness的值由代理提供,做如下修改:
let smiliness = dataSource?.smilinessForFaceView(self)
let smilePath = bezierPathForSmile(smiliness)
let smiliness = dataSource?.smilinessForFaceView(self) ?? 0.0
现在让我们来到实现代理的另一边,也就是HappinessViewController。
首先让它遵守协议:
class HappinessViewController: UIViewController,FaceViewDataSource{
import UIKit class HappinessViewController: UIViewController,FaceViewDataSource{ var happiness:Int = 50 {//0代表伤心,100代表开心 didSet{ happiness = max(min(happiness, 100), 0) println("happiness = \(happiness)") updateUI() } } func updateUI(){ } func smilinessForFaceView(sender: FaceView) -> Double? { <#code#> } }只需要输入代理方法的前几个字母系统会自动关联。代理方法不知道happiness是做什么的,因为它是模型层,控制器的任务就是为视图解析这个模型,你也会为了模型去解析视图,这个在手势识别的时候会讲到。
那么代理方法中的内容:
func smilinessForFaceView(sender: FaceView) -> Double? { return Double(happiness - 50)/50 }
现在回到FaceView中,有个小窍门:按下command+shift+O键然后键入关键字就能快速找到工程中的文件,当你的工程逐渐复杂起来的时候这是个非常不错的办法。
注意现在我们的storyboard中显示的是FaceView,记得之前我们设置的@IBdesignable吧?我们需要在控制器上拖拽一个faceview来显示
@IBOutlet weak var faceView: FaceView!
@IBOutlet weak var faceView: FaceView!{ didSet{ faceView.dataSource = self } }
func updateUI(){ faceView.setNeedsDisplay() }
一个很可爱的笑脸
【我们都爱Paul Hegarty】斯坦福IOS8公开课个人笔记17 Deledgation代理
标签:ios8 swift delegation 代理 内存管理
原文地址:http://blog.csdn.net/cg1991130/article/details/45075727