tonytran
tonytran

Reputation: 1078

using weak, strong self usage in block, core data, swift

Currently, I am doing a fetch in core data by following

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)")
        }
    }
})

And I am getting an error

Reference to property mainContext in closure requires explicit self to make capture semantics explicit

I notice that some of the solutions and they add self for the property in block.

Is it good to do that or should we create a weak or unowned to avoid retain cycle and what is the best way to handle this situation.

Upvotes: 1

Views: 837

Answers (1)

Rob Napier
Rob Napier

Reputation: 299355

Every time you use self in a block, you must consider the future of that block or you can create a reference cycle and leak memory (which is why Swift requires you to be explicit). A reference cycle most often occurs when a block captures (holds a strong reference to) self, some other object holds onto that block, and self holds onto that other object. In that configuration, there is a cycle that contains both self and the other object, so neither can ever deallocate.

This most often happens when the block is a handler for "every time X happens, please do this." The object that holds that block and does the notification is very often owned by the thing that wants to be notified. This is probably the most common kind of reference loop. It is generally resolved by making self weak.

performBlock, however, is not this kind of function. It executes the block and then releases it. In Swift terms it is @noescape (and in the future it may be marked that way and you won't need to use self. in noescape closures). Until the block executes, self cannot be deallocated, but after the block executes, the cycle is immediately broken. That probably is exactly what you wanted. So using self. here is fine, and there's no reason to add the complexity of a weak reference.

Upvotes: 5

Related Questions