I have my PersonListViewController working, it can access the plist,
use Core Data to create and store the objects, and then fetch them for
the table view.
In my PhotoListViewController I have a person ivar, which is set when
I push this table view from the PersonListViewController. I verified
the person is being set correctly based on the user selection.
When I try to access the person's photos all hell breaks loose, here
is the code block:
NSArray *photos = [person.photos allObjects];
NSLog(@"number of items in array %d", [photos count]); // this returns
the correct count
// the following lines cause a crash
Photo *firstPhoto = [photos objectAtIndex:0];
NSLog(@"photo name %@", firstPhoto.name);
I don't understand what I am missing here... any help is appreciated.
Thanks,
Wayne
I incorrectly assumed that Core Data was going to do some magic for
me. I assumed that if I had a Person object, I could just ask it for
its photos and get back the Photo objects, i.e.:
[person.photos allObjects];
What I got back was a bunch of garbled info, I assume (hopefully not
incorrectly again) that this is just information about the reference
relationship and not the object itself.
In order to achieve what I want, I had to another fetch where I get
all the Photos for the Person object I have.
Hope this helps someone,
Wayne
Kapsi
Kapsi
I too am getting this garbled info from logging the items array:
2010-03-04 20:01:17.254 Paparazzi[243:207] items array=(
<Photo: 0x1033a90> (entity: Photo; id: 0x1033290 <x-coredata://
DDA39EB0-5830-45C6-A21C-F79F696174C6/Photo/p1> ; data: <fault>),
<Photo: 0x1033ed0> (entity: Photo; id: 0x10332a0 <x-coredata://
DDA39EB0-5830-45C6-A21C-F79F696174C6/Photo/p2> ; data: <fault>),
<Photo: 0x1033fa0> (entity: Photo; id: 0x10332b0 <x-coredata://
DDA39EB0-5830-45C6-A21C-F79F696174C6/Photo/p3> ; data: <fault>)
)
Ive checked the data in the temp.sqlite file and its all there. Why
cant i log this array? And i guess because this is what i get, the
tableviewcontroller crashes when i set the indexpath.row to the
objectatindex for that array.
1. How are creating this array?
Hopefully you are using something like
[ marciosNSFetchedResultsController fetchedObjects] to instantiate
it.
2. How are you logging items from the array?
If you are doing something like NSLog(@"%@", [marciosArray
objectAtIndex:someIndex]), then you should get garbled results,
however if you ask each array item for its properties then you should
get the right data, i.e.
Photo *currentPhoto = [marciosArray objectAtIndex:someIndex];
NSLog(@"Photo name: %@, currentPhoto.name);
You should get what you are looking for.
Hope this helps,
Wayne
self.dataForTableView=[myConnection
fetchManagedObjectsForEntity:@"Photo" withPredicate:nil];
but ive also used this method:
NSFetchedResultsController *photosRC = [myConnection
fetchedResultsControllerForEntity:@"Photo" withPredicate:nil];
and i still get the garble. The problem was like you said, the way i
was logging the results. I got it now. So i guess I too was
expecting some magic to happen.
I guess this happens because the result of the fetch is an
NSFetchedResultsController object, but that means that with the
previous method it should work because that indeed returns an array.
Correct?
NSFetchedResultsController *photosRC = [myConnection
fetchedResultsControllerForEntity:@"Photo" withPredicate:nil];
NSError *error;
BOOL success = [photosRC performFetch:&error];
NSLog(@"%@", success);
[self.dataForTableView = photosRC fetchedObjects];
Photo *currentPhoto = [self.dataForTableView objectAtIndex:0];
NSLog(@"Photo name: %@", currentPhoto.photoName);
but it still crashes saying
Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: 'keypath name not found in
entity <NSSQLEntity Photo id=2>'
Does photosRC fetchedObjects return an array? So it should be set to
another array and be fine...
I'm not sure if I did it correctly, but it works. I think your issue
is that the relationship is expecting a NSSet of NSManagedObject
rather than an NSArray (as Kapsi mentioned). I can't tell, but I
think you are storing your list of photos in the relationship as an
array rather than just storing the image managed object into the
database.
I hope that helps.
Lenny
NSArray *FlickrIds = [NSArray arrayWithContentsOfFile:filePath];
for (NSDictionary *dict in twitterIds){
Photo *newPhoto = (Photo*)[NSEntityDescription
insertNewObjectForEntityForName:@"Photo"
inManagedObjectContext:managedObjectContext];
[newPhoto setPhotoName:[dict objectForKey:@"name"]];
[newPhoto setPhotoURL:[dict objectForKey:@"path"]];
[newPhoto setOwnerName:[dict objectForKey:@"user"]];
}
NSError *error;
if(![managedObjectContext save:&error]){
NSLog(@"Error:%@",error);
The sqlite file stores them, ive seen the values in there.
photo1.jpg, josh, Leaves on Fire (or whatever :))
and this is how i retrieve them:
NSFetchedResultsController *photosRC = [myConnection
fetchedResultsControllerForEntity:@"Photo" withPredicate:nil];
NSError *error;
BOOL success = [photosRC performFetch:&error];
[self.dataForTableView = photosRC fetchedObjects];
Photo *currentPhoto = [self.dataForTableView objectAtIndex:1];
NSLog(@"Photo name: %@", currentPhoto.photoName);
Is that your whole code to store the data? You should also have a
Person entity with a 1-many relationship to your Photo entity, right?
Can I see the code where you did that? I think that is where your
problem lies.
// setup our fetchedResultsController
fetchedResultsController = [flickr
fetchedResultsControllerForEntity:@"Person" withPredicate:nil];
// execute the fetch
NSError *error;
BOOL success = [fetchedResultsController performFetch:&error];
if (!success) {
// Handle the error.
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
exit(-1);
}
// save our data
[self setPeopleArray:(NSMutableArray *)[fetchedResultsController
fetchedObjects]];
Note, I am new to this but your line of code:
[self.dataForTableView = photosRC fetchedObjects];
looks wrong to me, it should be
self.dataForTableView = [photosRC fetchedObjects];
Hope this helps,
Wayne
thePhoto.name
since name is an attribute of thePhoto object. I don't know enough
about Cocoa to answer why
[thePhoto name] worked sometimes.
No idea why the [thePhoto name] works sometimes but am curious if
someone has an answer....
Wayne
Bill
Does it sound like what you did?
Thanks!!!!
I checked while reading plist file that I didn't already have the user
related to a photo. I thought it would be better for me to have my
database correct.
On 7 mar, 03:38, Lenny Teng <lenny_t...@yahoo.com> wrote:
> Jazmin - I went with approach #2. I created a dictionary and basically checked if the person key existed. That's a good question, though. I'd be curious how other people did this.
>
> ________________________________
> From: Jazmin <jazmi...@yahoo.com>
> To: iPhone Application Development Auditors <iphone-appd...@googlegroups.com>
> Sent: Sat, March 6, 2010 6:27:11 PM
> Subject: [iPhone-AppDev-Auditors] Re: Another Paparazzi 2 Question
>
> Hi Lenny,
> almost there!! I think. So I created the one-to-many relationship.
> Person -->one-to-many ---> Photo
> Now, how do you load the data:
> 1) If I load Photos first, then "person" attribute is not created yet
> in the database.
> 2) If I load Person I need to make sure I do not duplicate, for
> example "Josh" is twice in FakeData.sql.
> Checking if previous value of "user" is the same, does not seem right.
> We don't know if the xml is in order. I guess we can asume that in
> this case. Is there a better way to do it.
>
> Does it sound like what you did?
>
> Thanks!!!!
>
> --
> You received this message because you are subscribed to the Google Groups "iPhone Application Development Auditors" group.
> To post to this group, send email to iphone-appd...@googlegroups.com.
> To unsubscribe from this group, send email to iphone-appdev-aud...@googlegroups.com.
Person *person = [[Person alloc]init];
Photo *photo;
NSString *myPrevName = [NSString string];
NSError *error;
if ([myFetcher databaseExists]) {
//Load data
NSMutableSet *photoSet = [NSMutableSet setWithCapacity:5];
for (NSDictionary *item in dic) {
NSLog(@"user %@",[item valueForKey:@"user"]);
//if same as previous dont change it
if ([[item valueForKey:@"user"] isEqualToString: myPrevName ] )
{
NSLog(@"same don't init person, use the same");
} else {
person = (Person *)[NSEntityDescription
insertNewObjectForEntityForName:@"Person"
inManagedObjectContext:myObContext];
[person setName:[item valueForKey:@"user"]];
myPrevName = [item valueForKey:@"user"];
[photoSet removeAllObjects];
}
photo = (Photo *)[NSEntityDescription
insertNewObjectForEntityForName:@"Photo"
inManagedObjectContext:myObContext];
NSLog(@"path %@",[item valueForKey:@"path"]);
[photo setPath:[item valueForKey:@"path"]];
[photo setDesc:[item valueForKey:@"name"]];
[photo setBelongsTo:person];
[photoSet addObject: photo];
if (person)
[person setPhotos:photoSet];
if (![myObContext save:&error]) {
NSLog(@"Unresolved error %@", error);
}
}
thanks -wg
Did you write your Person/Photo classes yourself, or did you generate
them from the entities in the data model? I did the latter and it
added these methods to the Person class for me:
- (void)addPhotosObject:(Photo *)value;
- (void)removePhotosObject:(Photo *)value;
- (void)addPhotos:(NSSet *)value;
- (void)removePhotos:(NSSet *)value;
This means that in order to set up the database:
for each item in plist file
1) create instance of Photo in MOC and set its path & name
2) check if there is already an instance of the required Person
(could use a temporary NSMutableDictionary or fetch from MOC)
3) if not: create instance of Person in MOC and set its name
4) *** to relate photo to person call:
[person addPhotosObject:photo];
Does that make sense?
Vicki
Can I ask how you knew to add this line? I missed something in the
lecture or slides, because I thought that Core Data was creating the
relationship based on the xcdatamodel we created. This one line of
code turned out to be the key that was missing in my post from another
thread!
Thanks so much, Vicki! :-)
--Bill
I was blind to the fact that NSFetchedResultsController method uses a
Sort Descriptor @"name" which assumes you named your photo's name
atttribute 'name'. Which I didnt, i had called it 'photoName'. So
all you have to do is change @"name" to @"whateveryoucalledyours" and
be done with it.
Guys, dont yall think itd be better to post code to github.com where
the code is color-coded for easier modification? Im not saying post
the complete code. I understand the Stanford Moral and Ethics Code
has to be respected but since we do post code snippets here, why not
post them at github which would make it easier to read?
I personally think once Paparazzi 3 Deadline comes around, we should
post the completed codes for Paparazzi 2 in a place like that so we
can view the different options scatter all over this group. The
reason is that i think we are here mostly to learn for our own sake
(not for a grade) and once the deadline is past for those who are in
here for a grade, we could very well help ourselves through this web
of code weve managed to create :)
I personally feel a better work for keypath here is attribute, so to
simplify:
attribute "name" not found in entity Photo
i.e. Your photo class does not have a name attribute.
You can fix this in two ways, one is to update your Photo model the
other is to write a duplicate method in FlickrFetcher
for the method
- (NSFetchedResultsController *)fetchedResultsControllerForEntity:
(NSString*)entityName withPredicate:(NSPredicate*)predicate {
NSFetchedResultsController *fetchedResultsController;
Where you update the following line to reflect the key that you do
have for Photo
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]
initWithKey:@"name" ascending:YES];
Note, I have modified my above line already with the ascending order
to get the names alphabetical for the extra credit.
If you feel like you may want to take a chainsaw to core data, you
aren't alone :-)
Hope this helps,
Wayne