何时在Swift中使用闭包?

16

我已经学习iOS开发数月并渴望在我的编程模式中实现新事物。

现在我正在学习闭包,了解其语法的一些小知识,并知道它可以用于回调代替delegate。我还在一些UIViewAnimation和排序中实现了它。

但我真正想知道它的用途除此之外。也就是说,我们在基本编程中什么情况下应该使用闭包。就像我们想要从子代向父代发送信息时使用delegate一样。因此,在日常Swift编程中使用闭包的实际解释或简短示例将有所帮助吗?

能否有人告诉我这些闭包如何计算值?

reversed = sorted(names, { (s1: String, s2: String) -> Bool in return s1 > s2 } )

在这些示例中,有名称和闭包作为方法的参数..但是这实际上是如何计算的?

当在此动画代码中传递闭包时,您能否解释一下它们的工作原理?

UIView.animateWithDuration(duration: NSTimeInterval, 
    animations: (() -> Void)?, 
    completion: ((Bool) -> Void)?)

我真的想了解关于流程的内容?

3个回答

24
The two most commonly used cases are completion blocks and higher order functions in Swift.
Completion blocks: For example, when you have a time-consuming task and want to be notified when it is finished, you can use closures instead of a delegate (or many other things).
func longAction(completion: () -> ()) {
    for index in veryLargeArray {
        // do something with veryLargeArray, which is extremely time-consuming 
    }
    completion() // notify the caller that the longAction is finished 
}

//Or asynch version
func longAction(completion: () -> ()) {

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {

        for elem in veryLargeArray {
            // do something with veryLargeArray, which is extremely time-consuming
        }
        dispatch_async(dispatch_get_main_queue(), { 
            completion() // notify the caller that the longAction is finished 
        })
    }
}

longAction { print("work done") }

在上面的例子中,当你有一个耗时的任务时,你想知道for循环何时完成对非常大的数组的迭代。你将闭包{ println("work done") }作为函数的输入参数,该函数将在for循环完成其工作后执行,并打印"work done"。发生的情况是,你向longAction提供了一个函数(闭包)并将其命名为completion,当你在longAction中调用completion时,该函数将被执行。
高阶函数:你可以将闭包作为高阶函数的输入参数,例如:
let array = [1, 2, 3]
let smallerThanTwo = array.filter { $0 < 2 }

通过这个,你可以过滤掉小于2的数字。

更新 关于 sorted(可能)如何工作:

所以,思路是,sorted会遍历数组,并将两个相邻元素(i,i + 1)进行比较,如果需要,则交换它们。什么是“如果需要”?您提供了闭包{(s1:String,s2:String) -> Bool in return s1>s2} ,它将返回true如果s1 lexiographically大于s2。如果该闭包返回true,则sorted算法将交换这两个元素,并继续对下两个元素进行操作(如果未到达数组的末尾,则为i + 1,i + 2)。因此,基本上您必须为sorted提供一个闭包,告诉它“何时”交换两个元素。


1
我对这个有一点了解..您能否举个例子来解释一下完成块(completion block)? - user4790024
@copeME,我已更新我的答案,并解释了sorted函数的工作原理。 - Dániel Nagy
我希望有一个简单的闭包示例可用作完成块... - user4790024
@copeME 我想我会在晚上更新我的博客。 - Dániel Nagy
@copeME,稍晚一些,就像我承诺的那样,但这是它:http://danielnagy.hu/?p=73 - Dániel Nagy
显示剩余9条评论

4
一个闭包类似于:
{ (params) -> returnType in
  statements
}

以下是从苹果文档中使用它的原因:

  • 从上下文推断参数和返回值类型
  • 来自单表达式闭包的隐式返回
  • 简写参数名称
  • 尾随闭包语法

你能给我提供一个使用闭包作为完成块的好例子,以及描述其中发生的事情吗? - user4790024

3
  1. 通常,与其他函数不同的是,闭包没有名称。这意味着在您想要将代码块传递给某个函数而不将该代码块包装到命名方法中的每种情况下,可以使用它们。排序是最流行的例子。

  2. 闭包可以使用其边界外的变量。这被称为“捕获值”。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接