从不调用函数的完成处理程序有啥影响?

Posted

技术标签:

【中文标题】从不调用函数的完成处理程序有啥影响?【英文标题】:What are the effects of never calling a function's completion handler?从不调用函数的完成处理程序有什么影响? 【发布时间】:2019-01-25 21:47:49 【问题描述】:

如果您从不调用完成处理程序会发生什么?有没有什么副作用?我假设可能存在内存泄漏,但我找不到任何文档。

func completeMe(completionHandler: @escaping (String?) -> Void) 
   return

【问题讨论】:

@JoshCaswell 请详细说明?在什么情况下忽略完成处理程序可以/更糟? @JoshCaswell 我基于这样一个事实,即如果从不调用完成处理程序,应用程序将继续正常运行。我很好奇如果许多完成处理程序悬空,应用程序是否会受到任何影响。 @JoshCaswell 无法运行的代码会发生什么。它会永远等待,还是会超出范围? 未能调用完成处理程序违反了您与该方法的约定。称它为。故事结束。 【参考方案1】:

基本上,“完成处理程序”没有什么特别之处。这只是一个函数。

如果你有一个函数:

func f() 
    print("Hello, world")

而你没有调用它,那么会发生什么?好吧,什么都没有发生

现在,这意味着什么?正如 rmaddy 所提到的,如果一个函数一个完成,那么调用者当然希望调用该完成。 充其量,一个函数接受完成而调用者不关心完成是否曾经运行是不寻常的。*

想象一下这个函数被一个视图控制器调用,它在调用之前启动一个活动指示器,然后在完成时停止指示器。如果从不调用完成,则指示器永远不会停止旋转。

基本上就是这样。 如果未调用完成,则其代码不会运行。其效果完全取决于完成前后代码中发生的事情。


好的,你提到了内存......很多时候,完成处理程序将是一个匿名函数。在这种情况下, 会创建一个对象。但它与任何其他对象一样受制于相同的内存管理规则。没有泄漏只是因为它没有被调用。如果completeMe 看起来像这样:

func completeMe(_ completionHandler: (String) -> Void) 
    completionHandler("Hello, world")

你这样称呼它:

completeMe( self.detailLabel.text = $0 )

然后,当completeMe 返回时,为匿名函数创建的对象不会存在。如果您存储匿名函数:

func completeMe(_ completionHandler: @escaping (String) -> Void) 
    self.handler = completionHandler
    // Do other things

然后与任何其他对象发生相同的事情:匿名函数一直存在,直到该属性设置为另一个值(也假设没有其他对象引用它)支持>.

如果你传入一个命名函数,

func takeAString(_ s: String) 
    print(s)


completeMe(takeAString)

takeAString 的生命周期已经是程序的生命周期;这里没有内存管理问题。

如果传入实例方法,内存管理与传入实例本身一样。


*通常,如果可能失败,您将 a) 进行第二次“失败”完成或 b) 完成将通过其参数发出失败信号。

【讨论】:

【参考方案2】:

由于参数被命名为completionHandler,你的调用者将假定它无论如何都会被执行。

所以,回答你的问题,不会有任何固有的副作用,但它可能被认为是一种不好的做法。

【讨论】:

所以如果有一百万个块在等待completionHandler,什么都没有发生?我在想这些块(调用者)为它们分配了内存。 我认为方法返回时完成处理程序将超出范围 啊,我明白了。如果可能的话,你知道这方面的文件吗?我想在提供虚假信息之前进行 100% 的验证。

以上是关于从不调用函数的完成处理程序有啥影响?的主要内容,如果未能解决你的问题,请参考以下文章

是否可以创建一个从不同类调用函数的线程?

如何使用完成处理程序和参数调用函数

从 Timer 选择器函数 Swift 调用函数的完成处理程序

如何调用包含完成处理程序的函数?

第二次调用函数时未调用 Swift 完成处理程序

从 Java Script (TVML) 调用带有完成处理程序的 Swift 函数