委托与回调函数

作者: Sheepy | 来源:发表于2015-08-28 00:26 被阅读947次
    class ScrollViewCtrl: UIViewController, UIScrollViewDelegate {
      //some code
      override func viewDidLoad() {
        super.viewDidLoad()
        let scrollView = UIScrollView()
        scrollView.delegate = self
      }
    
      func scrollViewDidScroll(scrollView: UIScrollView) {
        //do something
      }
      //some code
    }
    

    这一段Swift代码稀疏平常,平常到可能有的同学从未想过这段代码背后做了什么。这里其实使用了一个同样稀疏平常却广为流传的设计模式——delegate模式。Delegate模式是在Cocoa开发中随处可见的一种设计模式,几乎贯穿于整个Cocoa框架。尤其是在我们最常使用的UIKit中,控制各类UI组件的最常用手段就是delegate跟Target-action(目标-动作,类似于一个监听事件)。至于回调函数么,其实跟委托没什么关系,然而曾经年少无知的我对这两个概念十分模糊,我想可能现在也有很多同学感到一头雾水,所以今天我想针对委托模式和回调函数分别讲一讲自己的理解,如有疏漏,欢迎各位批评指正。

    我们先回到开头的代码,看看到底发生了什么。ScrollViewCtrl是一个控制器,它confirm to(遵守,大致就是其他语言中实现一个接口的意思)UIScrollViewDelegate这个protocol(协议)。虽然Swift的委托实现跟协议息息相关,但我在这里不准备过多讨论协议的细节内容,只要知道它类似于其他语言的interface(接口)就可以了,只是Swift中的protocol不仅可以被class遵守, 还可以被structenum遵守。

    接着往下说,一开始我初始化了一个UIScrollView,并把它的delegate属性设置成self(即ScrollViewCtrl的一个实例)。然后在ScrollViewCtrl中写了一个scrollViewDidScroll方法。这样在这个scrollView滑动的时候就会执行scrollViewDidScroll里面的代码了。

    讲到这里我想大部分人还是不明白委托到底是怎么回事,因为我在这里只是使用了委托,具体的委托实现是UIKit框架写好的,这样对于理解委托来说无异于隔靴搔痒,所以下面我来实现一个完整的委托。

    //创建
    protocol MyDelegate: class {
      func delegateMethod()
    }
    
    class MyClass {
      weak var delegate: MyDelegate!
      
      func doSomethingWithAdditionalInfo() {
        //...
        delegate.delegateMethod()
      }
    }
    
    //使用
    class MyCtrl: UIViewController, MyDelegate {
      var myInstance: MyClass!
      override func viewDidLoad() {
        super.viewDidLoad()
    
        myInstance = MyClass()
        myInstance.delegate = self
        myInstance.doSomethingWithAdditionalInfo()
      }
    
      func delegateMethod() {
        println("Run")
      }
    }
    

    上面的代码是我随手写的,没跑过,理论上会输出"Run",各位可以试一试。这其实就是一个完整的委托模式了,当然在真实的情况下,一般doSomethingWithAdditionalInfo会在某个特定的时机运行delegate.delegateMethod这方法,譬如它可能会是个发送异步网络请求取数据的方法,然后在取到数据后调用delegate.delegateMethod,而取到数据后要做什么操作可以延迟到使用的时候再定义,即由使用者自行定义delegateMethod的具体操作。这是一种良好的解耦,非常适合在框架中使用。

    委托说完了,那什么是回调函数呢?其实回调函数做的事情跟委托很类似。不同的是,回调函数通过传递函数来实现延迟定义操作(在C这样的过程式语言中,需要通过函数指针作为参数传递来调用函数,而在支持高阶函数的函数式语言中,可以直接以函数为参数传递进行操作)。Swift对函数式编程的支持非常到位,所以可以轻松编写回调函数。依然以上面那段代码实现的功能为例,这次我们只要:

    //创建
    func doSomethingWithAdditionalOperation(additionalOperation: () -> ()) {
        //...
        additionalOperation()
      }
    
    //使用
    class MyCtrl: UIViewController, MyDelegate {
      override func viewDidLoad() {
        super.viewDidLoad()
        
        doSomethingWithAdditionalOperation {
          println("Run")
        }
      }
    }
    

    相关文章

      网友评论

        本文标题:委托与回调函数

        本文链接:https://www.haomeiwen.com/subject/gubhcttx.html