Question: Can you clarify the difference between fetchExisting(T) and edit(T) #102

Closed
opened 2025-12-29 15:24:39 +01:00 by adam · 4 comments
Owner

Originally created by @popwarfour on GitHub (Nov 18, 2016).

I'm currently running from swift3_develop

In both async and sync transaction classes the edit functions look to just be calling the fetchExisting behind the scenes anyway. Is there a difference between the two I'm not seeing?

Great library, looking forward to using this more moving forward!

Originally created by @popwarfour on GitHub (Nov 18, 2016). I'm currently running from swift3_develop In both async and sync transaction classes the edit functions look to just be calling the fetchExisting behind the scenes anyway. Is there a difference between the two I'm not seeing? Great library, looking forward to using this more moving forward!
adam closed this issue 2025-12-29 15:24:39 +01:00
Author
Owner

@JohnEstropia commented on GitHub (Nov 21, 2016):

@popwarfour Nothing, really. Just semantic naming:edit() adds nuance that this object can be edited. But that's entirely up to you.

@JohnEstropia commented on GitHub (Nov 21, 2016): @popwarfour Nothing, really. Just semantic naming:`edit()` adds nuance that this object can be edited. But that's entirely up to you.
Author
Owner

@popwarfour commented on GitHub (Nov 21, 2016):

figured as much, thanks

@popwarfour commented on GitHub (Nov 21, 2016): figured as much, thanks
Author
Owner

@rivera-ernesto commented on GitHub (Jan 16, 2018):

I see that edit runs more checks.

Where fetchExisting:

    public static func fetchExisting<D: DynamicObject>(_ object: D) -> D? {
        
        return self.defaultStack.fetchExisting(object)
    }

    public func fetchExisting<D: DynamicObject>(_ object: D) -> D? {
        
        return self.mainContext.fetchExisting(object)
    }

edit:

    public override func edit<D: DynamicObject>(_ object: D?) -> D? {
        
        CoreStore.assert(
            !self.isCommitted,
            "Attempted to update an entity of type \(cs_typeName(object)) from an already committed \(cs_typeName(self))."
        )
        
        return super.edit(object)
    }

    public func edit<D: DynamicObject>(_ object: D?) -> D? {
        
        CoreStore.assert(
            self.isRunningInAllowedQueue(),
            "Attempted to update an entity of type \(cs_typeName(object)) outside its designated queue."
        )
        guard let object = object else {
            
            return nil
        }
        return self.context.fetchExisting(object)
    }

    public func fetchExisting<D: DynamicObject>(_ object: D) -> D? {
        
        let rawObject = object.cs_toRaw()
        if rawObject.objectID.isTemporaryID {
            
            do {
                
                try withExtendedLifetime(self) { (context: NSManagedObjectContext) -> Void in
                    
                    try context.obtainPermanentIDs(for: [rawObject])
                }
            }
            catch {
                
                CoreStore.log(
                    CoreStoreError(error),
                    "Failed to obtain permanent ID for object."
                )
                return nil
            }
        }
        do {
            
            let existingRawObject = try self.existingObject(with: rawObject.objectID)
            if existingRawObject === rawObject {
                
                return object
            }
            return type(of: object).cs_fromRaw(object: existingRawObject)
        }
        catch {
            
            CoreStore.log(
                CoreStoreError(error),
                "Failed to load existing \(cs_typeName(object)) in context."
            )
            return nil
        }
    }

Any comment @JohnEstropia ?

@rivera-ernesto commented on GitHub (Jan 16, 2018): I see that `edit` runs more checks. Where `fetchExisting`: ```swift public static func fetchExisting<D: DynamicObject>(_ object: D) -> D? { return self.defaultStack.fetchExisting(object) } public func fetchExisting<D: DynamicObject>(_ object: D) -> D? { return self.mainContext.fetchExisting(object) } ``` `edit`: ```swift public override func edit<D: DynamicObject>(_ object: D?) -> D? { CoreStore.assert( !self.isCommitted, "Attempted to update an entity of type \(cs_typeName(object)) from an already committed \(cs_typeName(self))." ) return super.edit(object) } public func edit<D: DynamicObject>(_ object: D?) -> D? { CoreStore.assert( self.isRunningInAllowedQueue(), "Attempted to update an entity of type \(cs_typeName(object)) outside its designated queue." ) guard let object = object else { return nil } return self.context.fetchExisting(object) } public func fetchExisting<D: DynamicObject>(_ object: D) -> D? { let rawObject = object.cs_toRaw() if rawObject.objectID.isTemporaryID { do { try withExtendedLifetime(self) { (context: NSManagedObjectContext) -> Void in try context.obtainPermanentIDs(for: [rawObject]) } } catch { CoreStore.log( CoreStoreError(error), "Failed to obtain permanent ID for object." ) return nil } } do { let existingRawObject = try self.existingObject(with: rawObject.objectID) if existingRawObject === rawObject { return object } return type(of: object).cs_fromRaw(object: existingRawObject) } catch { CoreStore.log( CoreStoreError(error), "Failed to load existing \(cs_typeName(object)) in context." ) return nil } } ``` Any comment @JohnEstropia ?
Author
Owner

@JohnEstropia commented on GitHub (Jan 17, 2018):

Yes they do technically the same thing. The only difference is the semantic use, edit() being available only to transactions. Instances created with edit() are expected to be "edited" so extra checks are put in place for you for "just in case" scenarios. It is not available to read-only contexts (i.e. DataStack)

fetchExisting() on the other hand is mostly used for moving instances across main and background contexts. For this reason it is available under the same name to both read-only and read-write contexts.

Of course you can just use fetchExisting() everywhere if you wish. But edit() is there so you can take advantage of the expressiveness and safety.

@JohnEstropia commented on GitHub (Jan 17, 2018): Yes they do technically the same thing. The only difference is the semantic use, `edit()` being available only to transactions. Instances created with `edit()` are expected to be "edited" so extra checks are put in place for you for "just in case" scenarios. It is not available to read-only contexts (i.e. DataStack) `fetchExisting()` on the other hand is mostly used for moving instances across main and background contexts. For this reason it is available under the same name to both read-only and read-write contexts. Of course you can just use `fetchExisting()` everywhere if you wish. But `edit()` is there so you can take advantage of the expressiveness and safety.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/CoreStore#102