如何将回调添加到包含dispatch_after()的func?

时间:2015-07-30 20:42:50

标签: swift callback grand-central-dispatch

我想在几秒钟之后解散UIAlertView(不需要'ok'按钮)。

经过一番研究后,我发现我可以使用dispatch_after作为最终解除警报的延迟:

func delay(delay:Double, closure:()->()) {  
    dispatch_after(
        dispatch_time(
            DISPATCH_TIME_NOW,
            Int64(delay * Double(NSEC_PER_SEC))  // ...Int64.init() struct in Swift.
        ),
        dispatch_get_main_queue(), closure)
}

来源:Using dispatch_after vs NSTimer

上面的代码工作正常,但我想编辑闭包以允许发送者通过:UIViewController参数。这是我感到困惑的地方。

dispatch_after()格式为:

  

func dispatch_after(_ when:dispatch_time_t,_ queue:   dispatch_queue_t,_ block:dispatch_block_t)

这是我尝试过的(错误):

func delay(delay:Double, closure:(sender:UIViewController)->()) {
    dispatch_after(
        dispatch_time(
            DISPATCH_TIME_NOW,
            Int64(delay * Double(NSEC_PER_SEC))  // ...Int64.init() struct in Swift.
        ),
        dispatch_get_main_queue(), closure:(sender:UIViewController) in {

        })
}

问题:如何修复此问题以使块/闭包参数包含回调引用('sender:UIViewController')?

2 个答案:

答案 0 :(得分:1)

您不需要将sender“传递”到关闭位置。您只需要在闭包内引用sender

这称为capture,它是关闭闭包的有用之处。封闭将capture引用sender并将其与之一起使用。这就像魔术。

所以在sender在范围内的地方编写闭包。在闭包内引用sender。然后,将闭包传递给delay,一切都应该正常工作:

func closeAlert(sender: UIVewController) {

    let closure: () -> () = { 
        doSomethingWith(sender)
    }

    delay(3, closure: closure)
}

同样,秘诀是闭包捕获对sender的引用,当闭包传递给delay时,该引用随之携带。

答案 1 :(得分:0)

以下(删节)代码显示我的警报对话框(没有按钮)几秒钟后消失。

我当时正在考虑使用NSTimer但是我知道这是不明智的。
使用Swift + dispatch_after()是真正的方法。

enum AlertPurpose:Int {
    case none = 0  // ...default: no alert button.
    case simple // ...generic OK response.
    case timed
    case startBliss
    case noVideo
    case createdHashtag
    case missingProfileImage
    case profileSaved
    case settings
}

func closeAlert(sender: UIViewController) {
    let closure: () -> () = {
        sender.dismissViewControllerAnimated(true, completion: nil)
    }
    delay(3, closure)
}

func delay(delay:Double, closure:()->()) {
    dispatch_after(
        dispatch_time(
            DISPATCH_TIME_NOW,
            Int64(delay * Double(NSEC_PER_SEC))
        ),
        dispatch_get_main_queue(), closure)
}
...
...
...
} else if alertPurpose == .timed {
        closeAlert(sender as! UIViewController)

href