异步swift函数是否应该保留对对象的强引用?

时间:2016-09-13 00:18:01

标签: ios swift retain-cycle

我们实现并扩展了NSData,它将数据异步保存到URL。 这是函数的简短版本。

extension NSData {

    func writeToURL1(url:NSURL, completion: () -> Void)  {

        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { [weak self] in

            guard let strongSelf = self else { return }

            strongSelf.writeToURL(url, atomically: true)

            completion()
            })
    }
}

以下是我们如何使用它:

var imageData = UIImageJPEGRepresentation(image, 0.8)
imageData?.writeToURL(someURL) { in ... }

问题当然是如果imageData在写操作完成之前被释放strongSelf将为nil并且永远不会调用完成处理程序。

这个问题有两种解决方案。

  1. 删除[weak self](即在self中强烈引用writeToURL1
  2. 完成版块中的参考imageData(即imageData?.writeToURL(someURL) { in imageData = nil ... }
  3. 什么方法更适合Swift,我们应该采用什么方法?

    谢谢!

2 个答案:

答案 0 :(得分:4)

如果你不想让对象远离你的脚,你应该使用强大的参考(这样做不会创建一个参考周期);如果你不在乎物体是否远离你的脚,那么这是一个微弱的参考;如果你需要物体在周围,并且有一个强有力的保证物体不会在你的脚下离开,那么这是一个无主的参考,但是一个强大的参考会创造一个循环。

在您的情况下,您关心对象可能会消失,因为这意味着您无法保存它。由于您无法保证在该任务完成之前其他内容会使对象保持活动状态,因此您应该使用强引用。

关闭时对self的强引用是一个问题,因为它很容易以一个非显而易见的参考周期结束,但你知道参考将是一个事实在关闭执行后立即丢弃,所以这不是问题。

答案 1 :(得分:3)

听起来你只想强烈捕获对NSData对象的引用,因此在我看来删除[weak self]是最简单和最好的方法。通常,弱引用用于避免在闭包中捕获时保留周期。但是,您实际上并没有创建一个保留周期,只需通过在块中捕获self来保留一种方式。该块不是由self保留的,它只是将调用堆栈传递到dispatch_async,最终调用并释放它。因此,使用weak self没有要避免的保留周期,只需通过闭包进行保留即可。也就是说,您希望将数据保留在内存中,直到调用该闭包。