我试图更准确地理解斯威夫特的“关闭”。
但是@escaping
和完成处理程序
太难理解了
我搜索了许多Swift帖子和官方文件,但我觉得这仍然不够。
这是官方文件的代码示例
var completionHandlers: [()->Void] = []
func someFunctionWithEscapingClosure(completionHandler: @escaping ()->Void){
completionHandlers.append(completionHandler)
}
func someFunctionWithNoneescapingClosure(closure: ()->Void){
closure()
}
class SomeClass{
var x:Int = 10
func doSomething(){
someFunctionWithEscapingClosure {
self.x = 100
//not excute yet
}
someFunctionWithNoneescapingClosure {
x = 200
}
}
}
let instance = SomeClass()
instance.doSomething()
print(instance.x)
completionHandlers.first?()
print(instance.x)
听说使用< code>@escaping有两种方式和原因
第一个用于存储闭包,第二个用于异步操作目的。
以下是我的问题:
首先,如果doThings
执行,则一些FunctionSusEscape ingCloure
将使用闭包参数执行,并且该闭包将保存在全局变量数组中。
我认为闭包是{self.x=100}
{self.x=100}中保存在全局变量<code>completionHandlers</code>中的<code>self</code>如何连接到<code>实例</code>中<code>SomeClass</code>的对象?
其次,我理解了一些像这样的功能与回避关闭
。
要将局部变量闭包CompletionHandler
存储到全局变量'CompletionHandler,我们使用
@逃逸'关键字!
如果没有@转义
关键字和带有转义闭包的somefunction
返回,局部变量completionHandler
,将从内存中删除
@escaping
是将这种闭包保存在内存中
这样对吗?
最后,我只是想知道这种语法的存在。
也许这是一个非常初级的问题。
如果我们希望某个函数在某个特定函数之后执行。为什么我们不在特定函数调用后调用一些函数呢?
使用上述模式与使用转义回调函数之间有什么区别?
/*the long story short is that @escaping means that don't terminate the function life time until the @escaping closure has finished execution in the opposite of nonEscaping closure the function can be terminated before the closure finishes execution Ex:
*/
func fillData(completion: @escaping: () -> Void){
/// toDo
completion()
}
//___________________________
//The call for this function can be in either way's @escaping or nonEscaping :
fillData{
/// toDo
}
/* again the deference between the two is that the function can be terminated before finish of execution nonEscaping closure in the other hand the @escaping closure guarantees that the function execution will not be terminated before the end of @escaping closure execution. Hope that helps ***#(NOTE THAT THE CLOSURE CAN BE OF ANY SWIFT DATA TYPE EVEN IT CAN BE TYPEALIAS)*/
这里有一小部分例子,我用来提醒自己“逃避”是如何工作的。
class EscapingExamples: NSObject {
var closure: (() -> Void)?
func storageExample(with completion: (() -> Void)) {
//This will produce a compile-time error because `closure` is outside the scope of this
//function - it's a class-instance level variable - and so it could be called by any other method at
//any time, even after this function has completed. We need to tell `completion` that it may remain in memory, i.e. `escape` the scope of this
//function.
closure = completion
//Run some function that may call `closure` at some point, but not necessary for the error to show up.
//runOperation()
}
func asyncExample(with completion: (() -> Void)) {
//This will produce a compile-time error because the completion closure may be called at any time
//due to the async nature of the call which precedes/encloses it. We need to tell `completion` that it should
//stay in memory, i.e.`escape` the scope of this function.
DispatchQueue.global().async {
completion()
}
}
func asyncExample2(with completion: (() -> Void)) {
//The same as the above method - the compiler sees the `@escaping` nature of the
//closure required by `runAsyncTask()` and tells us we need to allow our own completion
//closure to be @escaping too. `runAsyncTask`'s completion block will be retained in memory until
//it is executed, so our completion closure must explicitly do the same.
runAsyncTask {
completion()
}
}
func runAsyncTask(completion: @escaping (() -> Void)) {
DispatchQueue.global().async {
completion()
}
}
}
快速完成处理程序转义
正如Bob Lee在他的博客文章《与Bob一起的Swift》中解释的那样:
假设用户在使用应用时正在更新该应用。您肯定希望在完成后通知用户。你可能想弹出一个框,上面写着:“恭喜你,现在,你可能会完全享受!
那么,如何在下载完成后才运行一段代码呢?此外,如何在视图控制器被移动到下一个视图控制器之后才激活某些对象?好吧,我们将找出如何设计一个像老板一样的人。
根据我丰富的词汇表,完成处理程序代表
在事情完成时做事
Bob的文章提供了有关完成处理程序的清晰信息(从开发人员的角度来看,它准确地定义了我们需要理解的内容)。
@转义闭包:
当在函数参数中传递闭包时,在函数体执行并返回编译器后使用它。当函数结束时,传递的闭包的作用域存在并存在于内存中,直到执行闭包为止。
有几种方法可以避免包含函数中的闭包:
> < li>
存储:当你需要将闭包存储在全局变量、属性或内存中存在的任何其他存储中时,调用函数被执行并返回编译器。
异步执行:当您在调度队列上异步执行闭包时,队列会在内存中为您保存闭包,供将来使用。在这种情况下,您不知道闭包何时会被执行。
当您尝试在这些场景中使用闭包时,Swift编译器将显示错误:
为了更清楚地了解这个话题,你可以在Medium上查看这个帖子。
添加一个或多个要点,每个ios开发人员都需要了解:
我目前正在学习swift,几个小时以来我一直在试图理解一个错误。由于查询,我试图从php脚本中获取一个xml文件,我使用一个完成处理程序作为回调来获取这些查询的结果。 问题是我对这些技术感到不舒服,它说缺少论据。 下面是使用完成处理程序的函数: 这是我调用这个函数的一段代码: 这段代码显示有关调用连接的此错误: 我做错了什么?为什么它要两个参数? 非常感谢您的帮助。 埃尔巴托
问题内容: 我正在试图做的是传递给函数,然后使用传递通过设置将返回。 我在中创建闭包时遇到了问题, 它引发了编译器错误/崩溃: 在斯威夫特,是根据文档应该包含的对象,就像Objective-C的版本。 这是我当前的代码: 编辑:似乎错误与不被视为数组有关。现在编译,但是我想集的时候得到什么,但无内。我检查了传递的,它们是有效的。 编辑2:打印后,我可以确认它返回了数据。但是仍然返回nil。 问题答
问题内容: 我在Utilities类中使用loadImage方法,并且在通过闭包返回图像时遇到了一些麻烦。基本上因为我的代码可能返回图像或错误,所以在调用该方法时将其分配给image属性是行不通的。 我在类的方法声明中使用的方法是否错误,还是应该以不同的方式调用该方法以预期潜在的不同结果?谢谢 问题答案: 将处理程序添加到您的 loadImage 函数中: 迅捷3 像这样调用func: 斯威夫特2
问题内容: 我是Swift和SpriteKit的新手。SpriteKit Actions的许多示例都在Objective C中,在Swift中我无法映射到它,也无法使用。 如果运行SKAction,并且在完成SKAction后又想做其他事情,那么如何在Swift中做到这一点呢? 任何想法将不胜感激。 编辑: 问题答案: 您的完成代码不会被调用,因为您的“死亡”操作将永远运行,这意味着它永远不会结束
问题内容: 我正在创建一个返回Dictionary的,但是当我在另一个类中调用此方法时,其值为nil。 然后,我尝试在另一个类中调用它,以便可以查看Dictionary 的值并基于该值显示数据。例如, 这里的问题是,当我调用函数时,我在尝试调用字典时收到一个值。 简而言之,我的问题是如何为完成处理程序分配值并在Xcode项目中的其他位置调用它? 问题答案: 您的问题很乱。您的示例代码无效,并且没有
问题内容: 我想知道如何为在Swift 3中创建的函数创建完成处理程序。这就是我在更新到Swift 3之前就完成函数的方式: 但是现在我无法找出目前可行的最佳方法。 问题答案: 在Swift 3中,闭包中的函数参数标签不见了。 删除所有出现并添加 并使用它