IOS-笔记7(代理)

Delegation

这是IOS开发中很常用的设计模式,用于将任务代理到其他类来执行,我不关心由谁来代理,也不关心你怎么执行,只要你把我要的传回来就行。这很适用于将View对数据和操作的请求传给Controlller,由Controller讲请求的数据和对应的操作响应传回给View。

在swift中使用Protocol可以非常顺畅的完成这个操作。


首先在View这里定义一个协议,来描述需要代理完成的工作:

protocol FaceDataSource : class{
    func smilinessForFaceView(sender:FaceView) -> Double?//1、将自己为参数传入Controller请求一个数据,Controller会实现这个方法
}
在这里没有参数也行,但是防止在Controller中需要直接访问View中的某些属性和方法,在这里将其传回去。


接下来在View类里设置一个协议类型的变量,Controller将把自己设置成这个dataSource,但是这是在Controller类中完成的,View并不知道是谁完成的这个代理:

Class FaceView{
      weak var dataSource: FaceDataSource?
    //2、设置一个公有变量为协议的类型,Controller将把自己设置成这个dataSource。
    //这就造成了一个问题:dataSource指向Controller,而在视图层次上我们还有一个由Controller指向FaceView的指针
    //这样就两个类就互相指向了对方,这时系统的自动引用计数就没用了,这样它们在内存中永远不会被释放,这是不可以的。
    //加上weak关键字就意味着这个指针指向的东西不能一直留在内存中,这样两个就都可以被释放了
    //不过这就又有一个问题了,weak只能修饰class(当然也只有class是在内存里的)不能修饰结构体和枚举,这样在协议的定义阶段加上只能由类实现就对了
}
同样是在这个类里,在需要使用时调用即可:

let smiliness = dataSource?.smilinessForFaceView(self) ?? 0.0 //3、使用代理传回来的数据,??的作用是当其左侧的表达式返回nil时使用右边的值

接下来就是在代理类里做的事了,首先当然要先声明自己实现协议,并实现协议要求的方法:

class HappinessViewController: UIViewController, FaceDataSource{//4、在这里声明实现协议,将自己作为代理
    func smilinessForFaceView(sender: FaceView) -> Double? {
        return Double(happiness-50)/50//5、实现协议的方法,为View解释Model层
    }
}

最后将自己指向View里的dataSource:

 
 
@IBOutlet weak var faceView: FaceView!{
        didSet{
            faceView.dataSource = self 
            //6、最后通过拖拽方法从StroyBoard里拖进来一个Faceview,来实现一个指向faceview的指针,并将其dataSource指向自己来完成一个代理
        }
    }
didset会在IOS初始化时设置faceView这个变量时执行,恰巧就是我们需要的时机

你可能感兴趣的:(IOS-笔记7(代理))