CoreData returning set with empty objects.

2019-09-06 01:36发布

问题:

I've been looking into this issue for the last day, so I think it's time to ask the question.

I created a one-to-many self referencing relation in CoreData to store contacts and group these contacts.

object http://i57.tinypic.com/rm6ul4.png

Contacts that haven't got a parent actually hold the "section name" of its children.

Section name (object without parent)
-------------------------------------
Contact 1
Contact 2

Code to save the objects (simplified):

 //Create Section
 section = [NSEntityDescription insertNewObjectForEntityForName:@"Contact" inManagedObjectContext:_managedObjectContext];
 [section setValue:self.sectionField.text forKey:@"name"];
 [section setValue:nil forKey:@"parent"];
 [_managedObjectContext save:&error];

 //Create contact
 NSManagedObject *newContact = [NSEntityDescription
                                   insertNewObjectForEntityForName:@"Contact"
                                   inManagedObjectContext:_managedObjectContext];
  [newContact setValue:self.nameField.text forKey:@"name"];
  [newContact setValue:self.numberField.text forKey:@"data"];
  [newContact setValue:[NSString stringWithFormat:@"%@",[LoginController getUser][@"id"]] forKey:@"user_id"];
  [newContact setValue:section forKey:@"parent"];

Tableviewcontroller:

In viewWilAppear I fetch all "parent"-objects (=sections) for the table view and assign them to the self.sections property.

//In viewWillAppear I get all "parent" objects
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Contact" inManagedObjectContext:_managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDescription];

// Set predicate
[request setRelationshipKeyPathsForPrefetching: [NSArray arrayWithObject:@"children"]];
NSPredicate *predicate = [NSPredicate predicateWithFormat: @"(parent == nil) AND (children.@count > 0)"];
[request setPredicate:predicate];
self.sections = (NSMutableArray *)[_managedObjectContext executeFetchRequest:request error:nil];

Then in cellForRowAtIndexPath I try to retrieve the child with index at indexPath.row within the parent with index at indexPath.section.

static NSString *CellIdentifier = @"Cell";

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}

[cell setSelectionStyle:UITableViewCellSelectionStyleBlue];
Contact * section = [self.sections objectAtIndex:indexPath.section];
NSArray * contacts = [section.children allObjects];
Contact * contact = [contacts objectAtIndex:indexPath.row];
NSLog(@"contact %@", contact.name);
[cell.textLabel setText:contact.name];
[cell.detailTextLabel setText:contact.data];

UIImageView *call = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"Call"]];
[cell setAccessoryView:call];

return cell;

The name of the contact won't show and I'm getting kind of desperate here. Any other insights?

回答1:

In addition to your own answer, you have another issue:

This line:

NSArray *contacts = [section.children allObjects];

is getting an array (allObjects) from a set. A set has no order so each time you request this array it will have a different order. This means that your cells don't have deterministic content, you will have duplicate rows and missing rows.

You could change the relationship to be ordered, or you could sort the array you get. You need to do one of these things before calling objectAtIndex: will return sane results.



回答2:

The NSManagedObject class for the entity was not correct. I wasn't aware of the tool to automatically generate these objects for core data entities.

New file.. > Core Data > NSManagedObject subclass > Choose the correct Datamodel > Choose the correct entity.