在块、核心数据、Swift 中使用弱、强自使用

ton*_*ran 1 memory-management weak-references objective-c ios swift2

目前,我正在通过以下方式获取核心数据

CoreDataStack.sharedIntance.backgroundContext.performBlock({
    let fetchRequest                =   NSFetchRequest(entityName: "Schedule")
    let sortDescriptor              =   NSSortDescriptor(key: "startTime", ascending: true)

    fetchRequest.sortDescriptors    =   [sortDescriptor]
    var result  =   [Schedule]()

    mainContext.performBlockAndWait { [unowned self] in
        do {
            result = try mainContext.executeFetchRequest(fetchRequest) as! [Schedule]
            success?(result)
        } catch {
            print("error is \(error)")
        }
    }
})
Run Code Online (Sandbox Code Playgroud)

我收到一个错误

闭包中对属性 mainContext 的引用需要显式 self 以使捕获语义显式

我注意到一些解决方案,它们self为块中的属性添加了。

这样做好还是我们应该创建一个weak or unowned以避免保留循环以及处理这种情况的最佳方法是什么。

Rob*_*ier 5

每次self在块中使用时,都必须考虑该块的未来,否则可能会创建引用循环并泄漏内存(这就是为什么 Swift 要求您显式地使用)。当一个块捕获(持有强引用)self,某个其他对象持有该块,并self持有该其他对象时,最常发生引用循环。在该配置中,存在一个包含两个self对象的循环,因此两者都不能释放。

当该块是“每次发生 X 时,请执行此操作”的处理程序时,最常发生这种情况。持有该块并执行通知的对象通常由想要通知的事物所拥有。这可能是最常见的参考循环类型。一般通过self弱化来解决。

performBlock然而,不是这种函数。它执行该块然后释放它。用 Swift 术语来说就是这样@noescape(将来它可能会以这种方式标记,并且您不需要self.在 noescape 闭包中使用)。在块执行之前,self不能被释放,但是在块执行之后,循环立即被打破。这可能正是您想要的。所以self.在这里使用就可以了,没有理由增加弱引用的复杂性。