我试图更准确地理解Swift 的"终结".

但是@escapingCompletion Handler太难理解了

我搜索了许多快速发布的帖子和官方文件,但我觉得还不够.

这是官方文件的代码示例

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)

我听说使用@escaping有两种方法和理由

第一个用于存储闭包,第二个用于异步操作.

The following are my questions:

首先,如果doSomething执行,那么someFunctionWithEscapingClosure将使用闭包参数执行,并且闭包将保存在全局变量数组中.

我认为闭包是{self.x=100}

保存在全局变量completionHandlers中的{self.x=self}中的self如何连接到SomeClassinstance对象?

第二,我理解这样的someFunctionWithEscapingClosure.

将局部变量闭包completionHandler存储到全局变量completionHandlerswe using@escaping`关键词!

如果不返回@escaping关键字someFunctionWithEscapingClosure,局部变量completionHandler将从内存中删除

@escaping是在记忆中保留这个结尾

是这样吗?

最后,我只是想知道这种语法的存在.

也许这是一个非常基本的问题.

如果我们想在某个特定函数之后执行某个函数.为什么我们不在特定的函数调用之后调用某个函数呢?

使用上述模式和使用转义回调函数之间有什么区别?

推荐答案

Swift Completion Handler Escaping & Non-Escaping:

正如Bob Lee在他的博客文章Completion Handlers in Swift with Bob中所解释的:

假设用户在使用应用程序时正在更新应用程序.你肯定想要

那么,如何在下载完成后才运行一段代码呢

根据我丰富的词汇表,补全处理程序代表

Do stuff when things have been done

Bob的帖子提供了关于完成处理程序的清晰信息(从开发人员的Angular 来看,它准确地定义了我们需要理解的内容).

@escaping closures:

在函数参数中传递闭包时,在函数体执行并返回编译器后使用闭包.当函数结束时,传递的闭包的作用域在内存中存在,直到执行闭包为止.

有几种方法可以在包含函数中转义闭包:

  • 存储:当需要将闭包存储在全局变量中时,将执行调用函数的内存中的属性或任何其他存储,并返回编译器.

  • 异步执行:当您在调度队列上异步执行闭包时,队列将为您保存内存中的闭包,以便将来使用.在这种情况下,您不知道何时执行闭包.

在这些情况下try 使用闭包时,Swift编译器将显示错误:

error screenshot

关于这个话题,你可以查看this post on Medium.

再增加一点,每个ios开发者都需要了解:

  1. Escaping Closure:转义闭包是在传递给它的函数返回后调用的闭包.换句话说,
  2. Non-escaping closure:在传递给它的函数中调用的闭包,即在它返回之前.

Swift相关问答推荐

SwiftData查询按日期排序的项的属性数组

如何消除SwiftUI中SF符号的填充

SWIFT中MAP的静态方法包装器

从Firebase播放音频文件不起作用

应该在ViewModel还是ViewController中使用"Task {}"?

DispatchQueue.main.asyncAfter 等同于 Swift 中的 struct 化并发?

从 actor 的 init 方法调用方法

在 Swift 的异步上下文中,如何指示我想要函数的同步版本?

如何自己实现同一个 iOS 16 锁屏圆形小部件?

如何打印出此 struct 中的数据?

创建 ViewModel 时 iOS 模拟器上的黑屏

为什么 Apple Scrumdinger Sample App 使用两个事实来源?

如何更改 Picker 的边框 colored颜色

在 Swift 中实现自定义异步序列

swift:修改字典中的数组

在 Swift 中强制崩溃的最简单方法

'#selector' 的参数不引用 '@objc' 方法、属性或初始化程序

ld:入口点(_main)未定义.对于架构 x86_64:Xcode 9

Swift 中的单元测试致命错误

滑动侧边栏菜单 IOS 8 Swift