本文介绍了如何在Swift 3中(幕后)实现转义的闭包?是否像在Objective-C中一样隐式地复制/保留了它们?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图了解转义的闭包如何在Swift 3中工作?来自Objective-C世界,对于闭包可以逃避其闭包函数返回的情况,您必须遵循以下原则:

I am trying to understand how escaping closures work in Swift 3? Coming from the Objective-C world, for scenarios where the closure could escape the return of its enclosing function you had to do something along these lines:

@property (nonatomic, copy/strong) void (^callback)(NSData *rawData);

-(BOOL)someFunctionThatConsumesABlock:(void (^)(NSData *rawData))block 
{
  if (callback) {
      self.callback = block;
      return YES;
  }
  return NO;
}

-(void)someFunctionThatExecutesAtSomeLaterPoint
{
  NSData *data = [self bytesFromSomeProcess];
  self.callback(data);
}

基本上在上面的目标C中的代码中,消耗该块的对象执行堆复制并强烈保留该块.这种强大的保留意义是有道理的,因为该块还需要超出函数范围之外,因为它也作为参数传递(因为其转义的闭包/块).

Basically in the above code in objective-C, the object consuming the block performs a heap copy and strongly retains the block. This strong retaining makes sense because the block needs to stick around beyond the scope of the function it is passed as an argument too (since its an escaping closure/block).

在Swift 3中,似乎上面的内容不再是必需的.所有需要做的只是将闭包注释为转义".那么Swift 3到底在做什么呢?它与Objective-C的作用相同吗?本质上,在Swift 3中转义的闭包是否也被传递的对象隐式地强烈保留?我看不出该语言还有什么其他方法可以实现这种效果,并让闭包坚持不懈".

In Swift 3, it seems the above is no longer necessary. All one needs to do is just annotate the closure as "escaping." So what is Swift 3 doing under the hood? Is it doing the same thing as objective-C? In essence do escaping closures in Swift 3 get implicitly strongly retained by the object they are being passed too? I dont see how else the language could achieve this and have the closures "stick around."

推荐答案

的确,当您将闭包另存为属性时,会隐式保留(强烈地)保留闭包.从Swift编程语言中自动引用计数:

It is true that closures are implicitly retained (strongly) when you save them as properties or otherwise. From The Swift Programming Language, Automatic Reference Counting:

(这就是捕获列表存在的原因:有助于避免意外的保留周期.)

(That's why capture lists exist: to help avoid accidental retain cycles.)

但是,我认为您可能误解了@escaping的目的(或者在较早版本的Swift中缺少@noescape). 会自动为您保存关闭项.而是,它仅向调用方指示您可能保存该闭包(闭包可能退出该函数的执行).这使编译器可以执行额外的优化,例如跳过保留.它还允许调用者在闭包内省略self.:

However, I think you may be misunderstanding the purpose of @escaping (or the absence of @noescape in older version of Swift). This does not automatically save the closure for you. Rather, it just indicates to the caller that you might save the closure (that the closure might escape the execution of the function). This allows the compiler to perform extra optimizations, such as skipping the retain. It also allows callers to omit self. inside the closure:

class Foo {
    var x = 3

    func test() {
        [1, 2, 3].map { $0 + x }
        // `self.x` is not necessary, because the map function's
        // closure is non-escaping
    }
}

((如果您有兴趣了解@escaping在幕后的真实情况,我不知道此类信息的确切来源,但是您可能会在关于SIL的讨论 SIL.rst 文档,也许还有了解WWDC16的Swift性能.)

(If you're interested in learning what's really going on under the hood with @escaping, I don't know of a definitive source for this kind of information, but you might find some useful things in this talk about SIL, the SIL.rst docs in the open-source project, and perhaps Understanding Swift Performance from WWDC16.)

这篇关于如何在Swift 3中(幕后)实现转义的闭包?是否像在Objective-C中一样隐式地复制/保留了它们?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-31 05:35