ManagedObjectContext question


#1

When we moved to CoreData we added code to BNRItemStore to get the Context, PersistentStoreCoordinator, etc. We did this in the init of that object so that once the store was created we could query the data using CoreData. This much I get.

The Silver Challenge asks me to have the capability to add new AssetTypes on the fly via the AssetTypePicker (view controller). I started with adding a “+” button to the top right of the NavigationBar by adding code to the init of the AssetTypePicker:

[code]- (id)init {

self = [super initWithStyle:UITableViewStyleGrouped];
if (self) {
    // Create a new bar button item for the right side that adds a new item
    UIBarButtonItem *rightBarButton = [[UIBarButtonItem alloc] 
                                       initWithBarButtonSystemItem:UIBarButtonSystemItemAdd 
                                       target:self 
                                       action:@selector(addNewAssetType:)];
    
    [[self navigationItem] setRightBarButtonItem:rightBarButton];
}

return self;

}[/code]

This created a button and when I click it the code I added to the same controller class for addNewAssetType: fires. So far so good. Now that I have that working the next logical thing to do would be to create a new BNRAssetType via CoreData and then save the context.

The question I have is: “Where is the correct/best place to put that code?”

I originally tried to add code to the AssetTypePicker that was similar to the code in BNRItemStore to grab the context and then create the new AssetType. Unfortunately when I setup a context in this class the array of existing BNRAssetTypes always came back as zero. Reading a bit on CoreData I get the feeling that I should have a single context item that I pass around from controller to controller and that I don’t want to create a new context in each controller - is that feeling correct?

Assuming we want a single context are the authors trying to get us to add code to the BNRItemStore for all interaction with the data store? As we have createItem: removeItem: and saveChanges: in BNRItemStore are the authors looking for me to add createAssetType: removeAssetType: etc in that same BNRItemStore? Is it smarter to pass the context from the store to the AssetTypePicker and have it do this work? It seems like they are guiding me to using the store for all data interaction.

Thoughts?


#2

The assumption that you reached in your last paragraph would be correct (not that I know what the authors were thinking). I followed the approach of having the BNRItemStore handle all changes. As you read further through the book (I cheated and checked some of the chapter on Model-View-Controller-Store), you’ll see that Homepwner follows the MVCS model. The BNRItemStore class is your “Store” in the MVCS paradigm. Hence, it’s best to have the BNRItemStore act as the gateway from and to your data through Core Data.

Now you seem to be on the right track by adding the navigation item button to add a new asset type. After a user touches the add button, they need to be able to give you the name of the new type that will be added to your asset types. Hence, you need to create another interface for the user to give you that data. For my app, I created a new UIViewController (let’s call it AssetAdderViewController) with a .xib file. The .xib file contained a simple label and a UITextField to allow the user to enter the name of the new asset type. In that view controller I added a navigation button “Done” that the user touches to confirm the entry of the new asset type.

Now back in your AssetTypePicker, inside the target method for your “addNewAssetType”, you’ll have to create an instance of AssetAdderViewController (don’t forget to import the header file first), and then “push” that controller. This will bring the .xib for AssetAdderViewController, and give the user the ability to give you the new asset type.

Now in AssetAdderViewController, you’ll have to create a new method that will be associated with the “Done” button (similar to what you’ve done in assetTypePicker), which the user will touch once they’ve entered their text. Inside that target-action method place a code similar to this:

BNRItemStore *store = [BNRItemStore sharedStore];
[store addAssetType:textField.text];

[self.navigationController popViewControllerAnimated:YES];

Inside your BNRItemStore you’ll have to implement a method similar to my example, “addAssetType”, inside which you’ll create your BNRAssetType and insert into your context.

Hope that helps.