views:

128

answers:

2

Hello,

I don't understand the output of NSLog for the array returned by a NSFetchRequest.

I'm reading my database and placing the contents in an array, looping through the array and then outputting the contents with NSLog. I don't quite understand the output in the log file. Code below:

-(void)createXMLFeed{
    //Fetch details from the database.
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Tabrss" inManagedObjectContext:managedObjectContext];
    [request setEntity:entity];
    NSError *error;
    self.stories = [[managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
    //[request release];

    // Count the number of items in the array and display in the log.
    int arrayItemQuantity = [stories count];
    NSLog(@"Array Quantity: %d", arrayItemQuantity);

    // Loop through the array and display the contents.
    int i;
    for (i = 0; i < arrayItemQuantity; i++)
        NSLog (@"Element %i = %@", i, [stories objectAtIndex: i]);

    [stories release]; 

    // Update log file.
    NSLog(@"Database read and XML feed created.");
}

Log file contents:

2010-06-24 10:09:56.918 TAB RSS[998:207] Array Quantity: 15
2010-06-24 10:09:56.919 TAB RSS[998:207] Element 0 = <NSManagedObject: 0x3b3dcb0> (entity: Tabrss; id: 0x3b06a60 <x-coredata://5B703215-A7D8-4E42-834E-A721D78E84BE/Tabrss/p22> ; data: <fault>)
2010-06-24 10:09:56.920 TAB RSS[998:207] Element 1 = <NSManagedObject: 0x3b3e1c0> (entity: Tabrss; id: 0x3b14720 <x-coredata://5B703215-A7D8-4E42-834E-A721D78E84BE/Tabrss/p23> ; data: <fault>)
2010-06-24 10:09:56.920 TAB RSS[998:207] Element 2 = <NSManagedObject: 0x3b3e370> (entity: Tabrss; id: 0x3b1ebd0 <x-coredata://5B703215-A7D8-4E42-834E-A721D78E84BE/Tabrss/p24> ; data: <fault>)
2010-06-24 10:09:56.921 TAB RSS[998:207] Element 3 = <NSManagedObject: 0x3b3e4e0> (entity: Tabrss; id: 0x3b1ecd0 <x-coredata://5B703215-A7D8-4E42-834E-A721D78E84BE/Tabrss/p25> ; data: <fault>)
2010-06-24 10:09:56.921 TAB RSS[998:207] Element 4 = <NSManagedObject: 0x3b3e660> (entity: Tabrss; id: 0x3b3b3f0 <x-coredata://5B703215-A7D8-4E42-834E-A721D78E84BE/Tabrss/p26> ; data: <fault>)
2010-06-24 10:09:56.922 TAB RSS[998:207] Element 5 = <NSManagedObject: 0x3b3e7d0> (entity: Tabrss; id: 0x3b09d20 <x-coredata://5B703215-A7D8-4E42-834E-A721D78E84BE/Tabrss/p27> ; data: <fault>)
2010-06-24 10:09:56.922 TAB RSS[998:207] Element 6 = <NSManagedObject: 0x3b3e940> (entity: Tabrss; id: 0x3b3cf20 <x-coredata://5B703215-A7D8-4E42-834E-A721D78E84BE/Tabrss/p28> ; data: <fault>)
2010-06-24 10:09:56.924 TAB RSS[998:207] Element 7 = <NSManagedObject: 0x3b3eac0> (entity: Tabrss; id: 0x3b3cf30 <x-coredata://5B703215-A7D8-4E42-834E-A721D78E84BE/Tabrss/p29> ; data: <fault>)
2010-06-24 10:09:56.924 TAB RSS[998:207] Element 8 = <NSManagedObject: 0x3b3ec40> (entity: Tabrss; id: 0x3b3cf40 <x-coredata://5B703215-A7D8-4E42-834E-A721D78E84BE/Tabrss/p30> ; data: <fault>)
2010-06-24 10:09:56.925 TAB RSS[998:207] Element 9 = <NSManagedObject: 0x3b3edb0> (entity: Tabrss; id: 0x3b3cf50 <x-coredata://5B703215-A7D8-4E42-834E-A721D78E84BE/Tabrss/p31> ; data: <fault>)
2010-06-24 10:09:56.925 TAB RSS[998:207] Element 10 = <NSManagedObject: 0x3b3ef20> (entity: Tabrss; id: 0x3b3cf60 <x-coredata://5B703215-A7D8-4E42-834E-A721D78E84BE/Tabrss/p32> ; data: <fault>)
2010-06-24 10:09:56.926 TAB RSS[998:207] Element 11 = <NSManagedObject: 0x3b3f090> (entity: Tabrss; id: 0x3b3cf70 <x-coredata://5B703215-A7D8-4E42-834E-A721D78E84BE/Tabrss/p33> ; data: <fault>)
2010-06-24 10:09:56.926 TAB RSS[998:207] Element 12 = <NSManagedObject: 0x3b3f200> (entity: Tabrss; id: 0x3b3cf80 <x-coredata://5B703215-A7D8-4E42-834E-A721D78E84BE/Tabrss/p34> ; data: <fault>)
2010-06-24 10:09:56.927 TAB RSS[998:207] Element 13 = <NSManagedObject: 0x3b3f380> (entity: Tabrss; id: 0x3b3cf90 <x-coredata://5B703215-A7D8-4E42-834E-A721D78E84BE/Tabrss/p35> ; data: <fault>)
2010-06-24 10:09:56.927 TAB RSS[998:207] Element 14 = <NSManagedObject: 0x3b3f500> (entity: Tabrss; id: 0x3b3cfa0 <x-coredata://5B703215-A7D8-4E42-834E-A721D78E84BE/Tabrss/p36> ; data: <fault>)
(gdb) continue
2010-06-24 10:09:57.932 TAB RSS[998:207] Database read and XML feed created.

What does this mean?:

<NSManagedObject: 0x3b3dcb0> (entity: Tabrss; id: 0x3b06a60 <x-coredata://5B703215-A7D8-4E42-834E-A721D78E84BE/Tabrss/p22> ; data: <fault> 

I want to actually see the contents of the field from the database.

I have 15 records in my database and 12 fields in each record. From my basic understanding, it looks like my stories array is holding the entire record from the database and not the individual fields. Maybe I need a 2D array to accomplish this, if so, how do I go about doing that?

Ultimately I want to loop through the array and create XML tags for each field. But one step at a time...

Thanks in advance, Stephen

+1  A: 

To view the individual fields of the objects in the array you must reference them directly. You are using this to show the objects in the array:

NSLog (@"Element %i = %@", i, [stories objectAtIndex: i]);

NSLog generates a description of each object when you use %@, which is often convoluted or useless. If you want to see the fields inside try something like this:

NSLog (@"Element %i contains fields: %d - %s - %d",i,[[stories objectAtIndex: i] getIntegerField],[[stories objectAtIndex: i] getStringField],[[stories objectAtIndex: i] getAnotherIntegerField]);

The values displayed will be the values returned by the getter functions of each object you are referencing in stories.

NWilkie
Thanks for the response, could you please elaborate a bit more on the getIntegerField, getStringField.I get an error stating these methods are not found.Is this something I have to code ??
Stephen
Sorry, I should have been more specific. Those were supposed to be general getter methods as I am not very familiar with the NSManagedObject class. There should be some methods for retrieving the information stored in the NSManagedObject and interpreting it, then you can use the nested method format to output that information. For example if you wanted to return the entity 'Tabrss' you would use [[stories objectAtIndex:i] entity]. I'm not quite sure what information was left out originally though.
NWilkie
+3  A: 

The output you are seeing is from the description method of the NSManagedObject class. It is just a human readable output intended for lightweight debugging purposes. You're not supposed to actually use it to parse or store data.

You don't see any detail about the data in the description dump because the managed objects were fetched as "faults" which means they are mere ghost of objects and contain no real data. To fetch the full fledged objects immediately, you would set you fetch request to do so with:

[request setReturnsObjectsAsFaults:NO];

... then when you log the objects you will see their data and relationships.

To actually use the data in the attributes, you have to query the attributes directly using one of the value methods such as valueForKey:@"attributeName".

Edit:

After editing your question, I think I need to elaborate.

You're thinking about Core Data all wrong. Core Data is not a database. It does not have fields. The return of a fetch request is not a table.

The relational database elements in Core Data are utterly optional and hidden. Instead, Core Data is an object graph manager that maintains the integrity of relationships between objects. The data is stored in objects and when you fetch from the persistent store you get back an object, not a field, column or row.

In this case, the fetch is returning a generic NSManagedObject that is configured to represent an entity Tabrss in your entity graph. Each managed object instance represents one logical Tabrss object. To get any value from from any Tabrss object you ask the managed object for the value associated with the name of the attribute of the Tabrss entity.

Suppose your Tabrss entity has a name attribute. To get the name of every Tabrss in your fetch you would use:

int i;
for (i = 0; i < arrayItemQuantity; i++)
    NSLog (@"Element %i = %@", i, [[stories objectAtIndex: i] valueForKey:@"name"]);

Or making it more explict:

NSManagedObject *aTabrss;
for (aTabrss in stories)
    NSLog(@"aTabrss.name=%@",[aTabrss valueForKey:@"name"]);

If you make a custom NSManagedObject subclass for the Tabrss entity you can query the attribute directly using the dot notation:

TabrssSubclass *aTabrss;
for (aTabrss in stories)
    NSLog(@"ATabrss.name=%@",aTabrss.name]);

The important thing it to remember you are dealing with full fledged objects and not arrays, matrixes, tables or some other dumb data structure. You get the data from from each individual object by sending a message asking for the value of one its attributes.

TechZen
Thanks for this post, I've just back round to reading it now. I managed to get this part of my project working. Also, thanks for the explanation about Core Data. I'm very new to iPhone development, but have learned a lot over the last few months. I have a strong programming background so when I saw Core Data, I naturally started using terminology that I was familiar with. When my App is finished I plan to go back to the start and review everything. Thanks again for the help.
Stephen
Yes, people with solid DB experience often have a harder time learning Core Data than novices. It's just natural to think about in terms of what you already know.
TechZen