如何在Swift中传递回调函数

时间:2014-09-07 23:57:48

标签: swift

我有一个简单的类,init方法采用Int和回调函数。

class Timer {
  var timer = NSTimer()
  var handler: (Int) -> Void

  init(duration: Int, handler: (Int) -> Void) {
      self.duration = duration
      self.handler = handler
      self.start()
  }
  @objc func someMethod() {        
      self.handler(10)
  }
}

然后在ViewController中我有:

var timer = Timer(duration: 5, handler: displayTimeRemaining)
func displayTimeRemaining(counter: Int) -> Void {
    println(counter)
}

这不起作用,我得到以下内容:

'Int' is not a subtype of 'SecondViewController'

编辑1:添加完整代码。

Timer.swift

import UIKit

class Timer {
    lazy var timer = NSTimer()
    var handler: (Int) -> Void

    let duration: Int
    var elapsedTime: Int = 0

    init(duration: Int, handler: (Int) -> Void) {
        self.duration = duration
        self.handler = handler
        self.start()
    }

    func start() {
        self.timer = NSTimer.scheduledTimerWithTimeInterval(1.0,
            target: self,
            selector: Selector("tick"),
            userInfo: nil,
            repeats: true)
    }

    func stop() {
        timer.invalidate()
    }

    func tick() {
        self.elapsedTime++

        self.handler(10)

        if self.elapsedTime == self.duration {
            self.stop()
        }
    }

    deinit {
        self.timer.invalidate()
    }
}

SecondViewController.swift

import UIKit

class SecondViewController: UIViewController {

    @IBOutlet var cycleCounter: UILabel!
    var number = 0

    var timer = Timer(duration: 5, handler: displayTimeRemaining)

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    @IBAction func btnIncrementCycle_Click(sender: UIButton){
        cycleCounter.text = String(++number)
        println(number)
    }

    func displayTimeRemaining(counter: Int) -> Void {
        println(counter)
    }
}

我刚开始使用Swift,所以我非常环保。你打算如何通过回调?我看过一些例子,我认为这应该是有效的。我的类是否因我传递回调的方式而被错误地定义了?

由于

3 个答案:

答案 0 :(得分:16)

好的,现在有了完整的代码我能够复制你的问题。我不是100%确定原因是什么,但我认为它与在实例化类之前引用类方法( displayTimeRemaining )有关。以下是一些解决方法:

选项1:在 SecondViewController 类之外声明处理程序方法:

func displayTimeRemaining(counter: Int) -> Void {
  println(counter)
}


class SecondViewController: UIViewController {    

  // ...
  var timer = Timer(duration: 5, handler: displayTimeRemaining)

选项2:通过将class关键字添加到函数声明中,将 displayTimeRemaining 转换为类型方法。

class SecondViewController: UIViewController {

  var timer: Timer = Timer(duration: 5, handler: SecondViewController.displayTimeRemaining)

  class func displayTimeRemaining(counter: Int) -> Void {
    println(counter)
  }

选项3:我相信这将是最符合Swift思维方式的内容 - 使用闭包:

class SecondViewController: UIViewController {

var timer: Timer = Timer(duration: 5) {
        println($0) //using Swift's anonymous method params
    }

答案 1 :(得分:6)

最简单的方式

override func viewDidLoad() {
        super.viewDidLoad()

        testFunc(index: 2, callback: { str in
            print(str)
        })

    }


    func testFunc(index index: Int, callback: (String) -> Void) {
        callback("The number is \(index)")
    }

答案 2 :(得分:0)

你的问题在于:

var timer = NSTimer()

您无法以这种方式实例化NSTimer。它具有为您生成对象的类方法。在这种情况下解决问题的最简单方法是使定义变得懒惰,如下所示:

lazy var timer = NSTimer()

这样,直到正确设置它的启动方法,实际上才会触及定时器的值。注意:这可能是一种更安全的方法。