2012-04-09 9 views
2

Ich spiele mit einer App herum, die verfolgt, wenn Menschen eine Veröffentlichung erhalten. Ich habe zwei Kerndatenentitäten, Publikation und Person, die zu viele Beziehungen haben, da jeder viele andere haben kann. Veröffentlichung < < - >> Person.Iterate durch iOS-Core-Daten-Beziehung

Ich versuche, durch die Beziehungen zu iterieren, so dass, wenn eine Person die Veröffentlichung erhalten hat, die Zelle Style-Häkchen sein sollte. Wenn sie nicht haben, dann sollte es Zellstil einfach sein. Hier ist, was ich bisher:

-(void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath { 

    Person *personForCell = (Person *) [fetchedResultsController objectAtIndexPath:indexPath]; 
    cell.textLabel.text = [NSString stringWithFormat:@"%@ %@", personForCell.firstName, personForCell.lastName]; 


    NSArray *issuesForPersonArray = [personForCell.issues allObjects]; 

    if ([issuesForPersonArray count] != 0) { 

    for (int i = 0; i <= [issuesForPersonArray count]; i++) { 
     if ([issuesForPersonArray objectAtIndex:i] == km) { 
      cell.accessoryType = UITableViewCellAccessoryCheckmark; 
     }else { 
      cell.accessoryType = UITableViewCellAccessoryNone; 
     } 
    } 
} 

Wenn ich laufen diese es werden alle Personen angezeigt werden, solange keine haben eine Beziehung zu dieser Veröffentlichung. Aber sobald ich ihren Namen wählen erhalte ich dieses Protokoll:

beenden app aufgrund nicht abgefangene Ausnahme 'NSRangeException', Grund: '* - [__ NSArrayI objectAtIndex:]: Index 1 über Grenzen [0 .. 0 ‚]

Hier ist die didSelectRow Methode:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    [tableView deselectRowAtIndexPath:[tableView indexPathForSelectedRow] animated:NO]; 
    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; 
    if (cell.accessoryType == UITableViewCellAccessoryNone) { 
     cell.accessoryType = UITableViewCellAccessoryCheckmark; 
     // Reflect selection in data model 
     Person *personSelected = (Person *) [fetchedResultsController objectAtIndexPath:indexPath]; 
     [publication addPersonObject:personSelected]; 


    } else if (cell.accessoryType == UITableViewCellAccessoryCheckmark) { 
     cell.accessoryType = UITableViewCellAccessoryNone; 
     // Reflect deselection in data model 
     Person *personSelected = (Person *) [fetchedResultsController objectAtIndexPath:indexPath]; 
     [publication removePersonObject:personSelected]; 

    } 

} 

ich bin sicher, dass ich darüber werde alles falsch, jede mögliche Hilfe wäre sehr geschätzt.

Ich habe es herausgefunden. Hier ist, was ich verwenden

-(void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath { 

    Person *personForCell = (Publisher *) [fetchedResultsController objectAtIndexPath:indexPath]; 
    cell.textLabel.text = [NSString stringWithFormat:@"%@ %@", personForCell.firstName, personForCell.lastName]; 

    NSMutableArray *issuesForPersonArray = [[personForCell.publication allObjects] mutableCopy]; 

    if ([issuesForPersonArray count] != 0) { 

     for (Publication *publicationForPerson in issuesForPersonArray) { 
      if (publicationForPerson == publication) { 
       cell.accessoryType = UITableViewCellAccessoryCheckmark; 
      }else { 
       cell.accessoryType = UITableViewCellAccessoryNone; 
      } 
     } 
    } 
} 

Antwort

1

Es ist ein grundlegender Konstruktionsfehler in Ihrem Code. Sie verwenden ein Oberflächenelement (das Häkchen), um Ihr Datenmodell zu informieren. Dies ist sehr fehleranfällig und bricht alle Regeln des MVC (Model-View-Controller) Programmierparadigmas.

Ihr grundsätzlicher Ansatz zum Anzeigen des Häkchens ist in Ordnung. Das Datenmodell wird herangezogen, um zu entscheiden, welches UI-Element verwendet werden soll. Es ist jedoch nicht die beste Möglichkeit, Ihre Objekte mit einem Index zu durchlaufen. Schleifen ist auch ziemlich teuer, wenn Sie die Tabellenansicht scrollen. Hier ist ein anderer Ansatz:

(Ich gehe davon aus km ist ein Verweis auf eine Instanz der Veröffentlichung Einheit in Frage.)

NSPredicate *predicate = [NSPredicate predicateWithFormat: 
    @"ANY issues == %@", km]; 
NSArray *filteredArray = [[personForCell allObjects] 
    filteredArrayUsingPredicate:predicate]; 
if (filteredArray.count > 0) // check 
else // uncheck 

stricty Sprechen es noch eine Iteration, aber der Rahmen es tut für Sie, damit Sie sich nicht mit diesen Out-of-Bounds-Fehlern befassen müssen.

Wenn Sie die Beziehung ändern möchten, sollten Sie eine ähnliche Methode verwenden diese Informationen abzurufen:

if (filteredArray.count > 0) [personSelected removeIssuesObject:km]; 
else [personSelected addIssuesObject:km]; 
[self.tableView reloadData]; 
+0

Danke für die Antwort. Ich werde den didSelectRowAtIndexPath sicher ändern. Ich werde deine Antwort auch mit dem Prädikat teilen. – Devroot

+0

Also, wenn ich das Prädikat versuche, ist das, was ich bekomme: 'NSInvalidArgumentException', Grund: 'Die linke Seite für einen ALL oder ANY Operator muss entweder ein NSArray oder ein NSSet sein.' – Devroot

+0

'NSPredicate * Prädikat = [NSPredicate PrädikatWithFormat: @ "ANY Problem ==% @", Veröffentlichung]; NSArray * filteredArray = [[personForCell.pubs allObjects] filteredArrayUsingPredicate: Prädikat]; if (filteredArray.count> 0) { // überprüfen cell.accessoryType = UITableViewCellAccessoryCheckmark; } else { // Deaktivieren Sie cell.accessoryType = UITableViewCellAccessoryNone; } ' – Devroot