PDA

View Full Version : Core Data Question




MadDoc
Nov 25, 2007, 03:01 AM
I've been reading a lot about Core Data and I have followed the example here (http://cocoadevcentral.com/articles/000085.php) with no problems.

What I am trying to build is a simple program that will allow me to list the wines I have in my cellar. I (ultimately) want a three-pane view with a browser (think the left-hand-side of iTunes) on the left, a list view displaying the name and vintage of my wines and a detail pane at the bottom with more data on the wine selected in the list view.

So far, I have built my entity model. I have the following entities:

1. Wine (cost, vintage, etc)
2. Vineyard (name, region, country)
3. Grape (variety, colour)

I have set up inverse relationships between them.

I have set up the array controllers (wines, grapes, vineyards) in IB.

I have bound the 'Name' column value to Wines.arrangedObjects.Name and the 'Vintage' column value to Wines.arrangedObjects.Vintage. This works great.

I tried binding the 'Vineyard' column value to Vineyards.selection.Name but this didn't work. I then tried binding the 'Vineyard' column value to Vineyards.arrangedObjects.Name but this wasn't right either.

I think it has something to do with the fact that I am not 'selecting' an entity as I am trying to display them all in a long list but I am not sure where I am going wrong.

Does this make any sense at all?

MadDoc,



slooksterPSV
Nov 25, 2007, 04:28 AM
Here let me try and help you out:

Ok so you have 3 separate entities right? Ok now I know you probably understand the basics of this, but here it goes:

Vineyard Object contains: NAME, REIGION, COUNTRY
Vineyard 1st object (we'll call Vineyard[0]) - selection -> Vineyard[0].selection->Table Column->Cell #->Name

Now you're selecting a Wine to enter a Vineyard or are you selection a Vineyard Object to enter in the data?

MadDoc
Nov 25, 2007, 04:41 AM
Here's the setup:

Entity 1 = Wine
Attributes:
- Name (string)
- Cost (float)
- Vintage (integer)
- Notes (string)
Relationships
- Vineyard
- Grape

Entity 2 = Vineyard
Attributes:
- Name (string)
- Country (string)
- Region (string)
Relationships:
- Wines (one-to many, inverse)

Entity 3 = Grape
Attributes:
- Variety (string)
- Colour (string)
Relationships:
- Wines (one to many, inverse)

The tableView I have has 4 columns:
- Vineyard Name
- Wine name
- Vintage
- Grape Variety

I want to list all of the defined WINES in this tableView. I am not sure how to list it correctly because I guess I need to use the 'Wines' array controller to feed the data to the tableView but I'm not sure how to populate the tableView with the data from the 'Vineyards' and the 'Grapes' array controllers. This differs from the CocoaDevCentral example because the tableview needs to display data from several different array controllers and I am confused about 'arrangedObjects' and 'selection' when it comes to bindings.

Is this clearer (sorry if it's not).

Thanks for trying to help - I really appreciate it.

MadDoc,

Eraserhead
Nov 25, 2007, 10:48 AM
I want to list all of the defined WINES in this tableView.

Bind the table column to the appropriate properties in the NSArrayController, e.g. name.

I am not sure how to list it correctly because I guess I need to use the 'Wines' array controller to feed the data to the tableView but I'm not sure how to populate the tableView with the data from the 'Vineyards' and the 'Grapes' array controllers.

You can do it in the same way as for Wines. You might find the source for D&D Manager (linked in my sig) helps you to work out what needs to be done, though it'll be a little complex for what you're doing.

SC68Cal
Nov 25, 2007, 11:17 AM
I've never used Core Data before, but it's really interesting how little they can really run away from using SQL. There seems to be a bit of abstraction but MadDoc's entity and attribute list looks exactly like SQL DDL.

Krevnik
Nov 25, 2007, 12:29 PM
I've never used Core Data before, but it's really interesting how little they can really run away from using SQL. There seems to be a bit of abstraction but MadDoc's entity and attribute list looks exactly like SQL DDL.

All Core Data provides is an abstraction from a DB object model in such a way that you don't have to write code to get the DB OM. Behind CoreData can be SQLite, XML, or a proprietary binary format. In 10.5 or later, you can even write your own storage back-ends and plug into CoreData if you need something beyond the 3 basic formats.

To answer the OP's question, your problem is that the wine table is based on the Wine array controller. Binding to the Vintage array controller is usually a bad idea because you mix up your bindings in a way that won't make any sense. Instead, you should be getting the vintage's name from the wine (this is the whole purpose of relationships). To do that you do something like:

Bind to Wines controller, with a keypath of: arrangedObjects.Vineyard.Name, and grape info can be gotten via arrangedObjects.Grape.Variety... If you bind to anything other than the entity you use in the table, it just won't display right, even if you did get it working.

MadDoc
Nov 25, 2007, 05:35 PM
Thanks Krevnik - yet again you appear to have been my saviour :)

I'm at work at the moment so I can't check it out until I get home but can I just ask one further question:

Do I still need an array controller for the Vineyard and Grape entities or do I just need one for the Wines entity?

Thanks,

MadDoc

Krevnik
Nov 25, 2007, 07:48 PM
Thanks Krevnik - yet again you appear to have been my saviour :)

I'm at work at the moment so I can't check it out until I get home but can I just ask one further question:

Do I still need an array controller for the Vineyard and Grape entities or do I just need one for the Wines entity?

Thanks,

MadDoc

No, just the entities you need to have direct control over (so unless you have a list of grapes and vineyards somewhere, you don't need controllers for them).

MadDoc
Nov 26, 2007, 03:07 AM
Something is really broken and I am not sure why :(

I thought some images would help illustrate.

My core data model (in Xcode):

http://garrypettet.com/images/coredata/model.tiff

Application window in IB:

http://garrypettet.com/images/coredata/main_window.tiff

The Wines array controller in IB (first attributes then bindings):

http://garrypettet.com/images/coredata/wines_attributes.tiff http://garrypettet.com/images/coredata/wines_bindings.tiff

The vineyard column bindings:

http://garrypettet.com/images/coredata/vineyard_column.tiff

The wine name column bindings:

http://garrypettet.com/images/coredata/name_column.tiff

The grape variety column bindings:

http://garrypettet.com/images/coredata/grape_column.tiff

In the 'Model Key Path' field I have tried Vineyard.Name instead of arrangedObjects.Name to no avail.

When I run the app - nothing happens (apart from the odd crash) when I click the add button (this is bound to the add: method of the Wines array controller).

Am I missing something really obvious or have I done something really wrong?

MadDoc

Krevnik
Nov 26, 2007, 04:37 AM
In the 'Model Key Path' field I have tried Vineyard.Name instead of arrangedObjects.Name to no avail.

When I run the app - nothing happens (apart from the odd crash) when I click the add button (this is bound to the add: method of the Wines array controller).

Am I missing something really obvious or have I done something really wrong?

MadDoc

Notice that the bindings already have 'arrangedObjects' in them for the controller key. The two fields are combined internally into a single string. You didn't need to copy/paste my exact text. Regardless, you should be able to follow relationships like they were fields. "Vineyard.Name" should work as long as you only have one Vineyard relationship in a single Wine. The only reason it shouldn't work is if you don't have a Vineyard object attached to the Wine. Without that, you won't be able to see/edit the name field for it.

You CANNOT follow the Grapes relationship though (without specifying which index), as you have it setup. It is a one-to-many relationship, meaning when you do a Grapes.Name, your OM doesn't know /which/ object in the relationship you are talking about. This is more of an FYI...

In general, you want to avoid one-to-many relationships if at all possible, and at the very least not use one-to-many relationships for paths you will actually try to use.

slooksterPSV
Nov 26, 2007, 08:33 AM
http://developer.apple.com/cocoa/coredatatutorial/index.html

Maybe that'll help, that helped me out, and I think you create a one-to-many relationship model in the tut as well; yes it does it's movie 3, but this walks you through an application that uses a one-to-many relationship and all that. It helped me understand CoreData and the video's are small so you can run it on DSL, Cable or Satellite quickly, heck even dial-up wouldn't be a pain lol.

Hope that helps.