Editing in child context

On page 373 you talk about using child contexts, and you’re creating the child context and passing that into the edit view controller. This seems wrong to me. You’re forcing the caller to know implementation details by doing this, right?

It seems to me that the edit view controller should handle the creation of a child context itself. You pass in the persistentStore.viewContext and either a nil or an NSManagedObject depending on whether you’re creating new or editing existing. The edit view controller then handles creating the child context.

@gargoyle Thanks very much for your question. I looked at the most recent version, as well as the previous version of Core Data by Tutorials, and neither book goes as far as page 373. Could you please check to see you are referencing the content correctly? In the most recent version, the chapter “Multiple Managed Contexts” starts on page 233. :slight_smile:

Having said that, the answer to your question I believe is on page 250:

Note: You might be wondering why you need to pass both the managed object and the managed object context to the detailViewController, since managed objects already have a context variable. This is because managed objects only have a weak reference to the context. If you don’t pass the context, ARC will remove the context from memory (since nothing else is retaining it) and the app will not behave as you expect.

In addition (and I believe this is what you were trying to get at), the reason why the child context is created, and then passed to the detailViewController, instead of simply passing the parent MOC, and creating the child MOC inside the detailViewController is because the child MOC is needed to retrieve the childEntry object which is required to be sent the detailViewController. The explanation for this is also given on the same page:

  1. Next, you retrieve the relevant journal entry using the child context’s object(with:) method. You must use object(with:) to retrieve the journal entry because managed objects are specific to the context that created them. However, objectID values are not specific to a single context, so you can use them when you need to access objects in multiple contexts.

In other words, the child MOC is created so that it may be used immediately, and is then passed to the detailViewController so that the same object may be reused, instead of creating a new one.

I hope this helps!

All the best!

What I’m saying is instead of creating the child context ‘outside’ and passing it in, just pass the actual item that you want to edit. Inside the view controller you would then create the child context, call object(with:) etc… and then all of those details are encapsulated inside of the view controller itself.

I understand what you’re saying, however, I’m pointing out that the child context is needed to fetch the journal entry PRIOR to being passed into the detailViewController.

Please explain why, because I seem to be doing this in my current app without issue.

    childContext =  NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
    
    if let ticket = ticket {
        // Editing an existing ticket
        parentContext = ticket.managedObjectContext!
    }
    
    childContext.parent = parentContext
    
    if let objectID = ticket?.objectID {
        ticket = (childContext.object(with: objectID) as! Ticket)
    } else {
        ticket = Ticket(context: childContext)
    }

I’ve checked both the Swift 3, and Swift 4 versions of the book, and I unfortunately can’t seem to find the example you are referring to. Can you please verify what book it is you are using, and where your example can be found? I personally am referring to the content that is found in Core Data by Tutorials.

No, I’m saying that’s the code I’m using right now, which seems to work fine, and is all done inside of the “Edit” view controller.

The typical pattern for using a Managed Object Context (MOC) is to create it at the time of your app’s launch as part of the Core Data Stack, which usually means triggered by the AppDelegate. Once the MOC is created, it is then passed as a property from ViewController to ViewController within your app, so that you’re maintaining the same reference throughout the lifecycle of the app, and you’re not creating the object again, and again. So while the MOC can be passed as a property from VC to VC, I would agree with you that a child MOC should be created when it is needed, but not before.

Having said that, your code is similar to the one used as an example in the book “Core Data by Tutorials”, however, the one area of concern that I do have is the line:

if let ticket = ticket {
    // Editing an existing ticket
    parentContext = ticket.managedObjectContext!
}

The reason why I’m mentioning this is that it leaves open the possibility that ticket may at some point be nil, which would mean that the parent context for the child MOC is never set, and thus potentially cause a crash. If there is no possibility for the if let clause to fail, then consider perhaps removing it altogether to be safe.

Here is the sample code that we use in our book, “Core Data by Tutorials”:

// 1
let childContext = NSManagedObjectContext(
  concurrencyType: .mainQueueConcurrencyType)
childContext.parent = coreDataStack.mainContext
// 2
let childEntry = childContext.object(
  with: surfJournalEntry.objectID) as? JournalEntry

Here is a link to our recent tutorial on Multiple Managed Object Contexts as a reference for you to see some of the examples we show.

I hope this helps!

All the best!

That is right , the child MOC is created so that it may be used immediately.and the same object may be reused, instead of creating a new one.


my unity tutorials

Please see this example.. All I’m trying to show is there is no reason to create the CHILD contexts at the caller. You should encapsulate all of that into editor view controller and not require all of your callers to prepare that child context for you.

The only way ticket would be nil is if you are creating a new ticket, and in that case you’ve passed in the parent context to use for creation. It just makes everything cleaner this way as you only handle the child context one time, in the ticket editor, no matter how many different places in your code might want to pop up that editor.

This topic was automatically closed after 166 days. New replies are no longer allowed.