2010-07-29 4 views
0

Dans un autre question concernant l'ajout d'une ligne insert dans un UITableView soutenu par Core Data, j'ai mentionné que mon NSFetchedResultsController assigne chaque objet qu'il récupère à une section séparée dans mon UITableView. J'ai supposé que c'était simplement le comportement par défaut, mais Marcus S. Zarra a dit qu'il pourrait y avoir quelque chose de mal avec ma configuration du contrôleur ou mes méthodes de délégué de source de données. J'avoue, mon code se sent un peu comme Frankenstein avec des parties tirées des docs Apple et de nombreux tutoriels. Ceci est mon premier programme et ma première fois à l'aide des données de base, donc s'il vous plaît soyez doux;)Pourquoi NSFetchedResultsController affecte-t-il des objets récupérés à plusieurs sections UITableView?

en-tête du contrôleur Ma vue de table est la suivante:

#import <UIKit/UIKit.h> 
    #import "RubricAppDelegate.h" 


    @interface ClassList : UITableViewController { 
     NSMutableArray *classList; 
     NSFetchedResultsController *fetchedResultsController; 
     NSManagedObjectContext *managedObjectContext; 

} 

@property(nonatomic,retain) NSMutableArray *classList; 
@property(nonatomic, retain) NSFetchedResultsController *fetchedResultsController; 
@property(nonatomic, retain) NSManagedObjectContext *managedObjectContext; 

- (IBAction) grade:(id)sender; 

@end 

Mon fichier de mise en œuvre comprend un tas de données de test factices. J'ai inclus cela dans le cas où j'utilise des méthodes incorrectes pour instancier les objets de données de base. Fondamentalement, je veux savoir si mon NSFetchedResultsController devrait pas retourner mes objets (dans ce cas, les instances de myClass) dans des sections distinctes. Si oui, que fais-je pour créer ce problème? L'objectif ultime pour le moment est de pouvoir ajouter une cellule d'insertion en haut de ma table (je sais que la mettre en bas est «standard», mais j'aime son apparence dans les applications). ça fait l'inverse). Vous remarquerez que mon -tableView:editingStyleForRowAtIndexPath: définit le style de cellule de la section 0 à insérer, mais bien sûr j'ai besoin de comprendre comment démarrer la liste de myClass.classTitle à la cellule 1 au lieu de la cellule 0 (c'est pourquoi je veux déterminer si chaque l'objet affecté à sa propre section est normal).

Voici mon dossier de mise en œuvre:

#import "ClassList.h" 
#import "ClassRoster.h" 
#import "RubricAppDelegate.h" 
#import "Student.h" 
#import "myClass.h" 


@implementation ClassList 

@synthesize classList; 
@synthesize fetchedResultsController; 
@synthesize managedObjectContext; 

#pragma mark - 
#pragma mark View lifecycle 


- (void)viewDidLoad { 
    [super viewDidLoad]; 

    self.editing = YES; 

    RubricAppDelegate *appDelegate = (RubricAppDelegate *)[[UIApplication sharedApplication] delegate]; 
    managedObjectContext = [appDelegate managedObjectContext]; 
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"myClass" inManagedObjectContext:managedObjectContext]; 
    NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease]; 
    [request setEntity:entity]; 

    //test data 
    myClass *newClass = (myClass *) [NSEntityDescription insertNewObjectForEntityForName:@"myClass" inManagedObjectContext:managedObjectContext]; 
    newClass.classTitle = @"UFDN 1000"; 
    NSNumber *ID = [NSNumber numberWithInt:1]; 
    newClass.classID = ID; 

    Student *newStudent = (Student *) [NSEntityDescription insertNewObjectForEntityForName:@"Student" inManagedObjectContext:managedObjectContext]; 
    newStudent.classID = ID; 
    newStudent.studentName = @"Andy Albert"; 
    newStudent.studentUsername = @"albera"; 
    [newClass addStudentsObject:newStudent]; 

    newStudent.classID = ID; 
    newStudent.studentName = @"Bob Dole"; 
    newStudent.studentUsername = @"doleb"; 
    [newClass addStudentsObject:newStudent]; 

    newStudent.classID = ID; 
    newStudent.studentName = @"Chris Hanson"; 
    newStudent.studentUsername = @"hansoc"; 
    [newClass addStudentsObject:newStudent]; 

    myClass *newClass2 = (myClass *) [NSEntityDescription insertNewObjectForEntityForName:@"myClass" inManagedObjectContext:managedObjectContext]; 
    newClass2.classTitle = @"UFDN 3100"; 
    ID = [NSNumber numberWithInt:2]; 
    newClass2.classID = ID; 

    newStudent.classID = ID; 
    newStudent.studentName = @"Danny Boy"; 
    newStudent.studentUsername = @"boyd"; 
    [newClass2 addStudentsObject:newStudent]; 

    newStudent.classID = ID; 
    newStudent.studentName = @"James Matthews"; 
    newStudent.studentUsername = @"matthj"; 
    [newClass2 addStudentsObject:newStudent]; 

    newStudent.classID = ID; 
    newStudent.studentName = @"Aaron Todds"; 
    newStudent.studentUsername = @"toddsa"; 
    [newClass2 addStudentsObject:newStudent]; 


    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"classID" ascending:YES]; 
    NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor]; 
    [request setSortDescriptors:sortDescriptors]; 
    [sortDescriptor release]; 
    NSError *error; 

    fetchedResultsController = [[NSFetchedResultsController alloc] 
               initWithFetchRequest:request 
               managedObjectContext:self.managedObjectContext 
               sectionNameKeyPath:@"classTitle" cacheName:nil]; 

    [fetchedResultsController performFetch:&error]; 

    UIBarButtonItem *gradeButton = [[UIBarButtonItem alloc] 
            initWithTitle:@"Grade" 
            style:UIBarButtonItemStylePlain 
            target:self 
            action:@selector(grade:)]; 
    self.navigationItem.rightBarButtonItem = gradeButton; 

    [gradeButton release]; 

} 

- (IBAction) grade:(id)sender { 

} 

#pragma mark - 

#pragma mark Table view data source 

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 
    NSLog(@"Number of sections = %d", [[fetchedResultsController sections] count]); 
    return ([[fetchedResultsController sections] count]); 

} 

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 
    // Return the number of rows in the section. 
    id <NSFetchedResultsSectionInfo> myClass = [[fetchedResultsController sections] objectAtIndex:section]; 
    NSLog(@"Number of classes = %d", [myClass numberOfObjects]); 

    return [myClass numberOfObjects]; 

} 

// Customize the appearance of table view cells. 
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 

    static NSString *CellIdentifier = @"Cell"; 

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

     myClass *theClass = [fetchedResultsController objectAtIndexPath:indexPath]; 
     NSLog(@"Class name is: %@", theClass.classTitle); 
     cell.textLabel.text = theClass.classTitle; 
    } 

    return cell; 
} 

    - (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath 
    { 
     if (indexPath.section == 0) { 
      return UITableViewCellEditingStyleInsert; 
     } 
     else return UITableViewCellEditingStyleDelete; 
    } 


    // Override to support editing the table view. 
    - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { 

     if (editingStyle == UITableViewCellEditingStyleDelete) { 
      myClass *result = (myClass *)[fetchedResultsController objectAtIndexPath:indexPath]; 
      [managedObjectContext deleteObject:result]; 
      [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:YES]; 

     } 
     else if (editingStyle == UITableViewCellEditingStyleInsert) { 

     } 
    } 

    #pragma mark - 
    #pragma mark Table view delegate 

    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 
     // Navigation logic may go here. Create and push another view controller. 
     /* 
     <#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:@"<#Nib name#>" bundle:nil]; 
     // ... 
     // Pass the selected object to the new view controller. 
     [self.navigationController pushViewController:detailViewController animated:YES]; 
     [detailViewController release]; 
     */ 
    } 


    #pragma mark - 
    #pragma mark Memory management 

    - (void)didReceiveMemoryWarning { 
     // Releases the view if it doesn't have a superview. 
     [super didReceiveMemoryWarning]; 

     // Relinquish ownership any cached data, images, etc that aren't in use. 
    } 

    - (void)viewDidUnload { 
     // Relinquish ownership of anything that can be recreated in viewDidLoad or on demand. 
     // For example: self.myOutlet = nil; 
    } 


    - (void)dealloc { 
     [classList release]; 
     [super dealloc]; 
    } 


    @end 

Mon RubricAppDelegate est essentiellement identique à la documentation Apple pour la mise en place de base de données NSManagedObjectContext, NSPersistentStoreCoordinator, etc. Cependant, si vous pensez qu'il pourrait y avoir un problème là-bas, faites le moi savoir et je l'afficherai. Edit: J'ai oublié de mentionner deux raisons pour lesquelles je sais que chaque objet est assigné à une section différente.

1) NSLog(@"Number of sections = %d", [[fetchedResultsController sections] count]); à l'intérieur de -numberOfSectionsInTableView: renvoie le nombre d'objets myClass dont je dispose.

2) Si je règle -numberOfSectionsInTableView: pour retourner 1, ma table affiche seulement un objet et coupe le reste.

Répondre

2

Vous avez des sections car vous indiquez au contrôleur de résultats récupérés de les créer en transmettant une valeur non nulle pour sectionNameKeyPath: lors de l'initialisation de la FRC.

Change:

fetchedResultsController = [[NSFetchedResultsController alloc] 
              initWithFetchRequest:request 
              managedObjectContext:self.managedObjectContext 
              sectionNameKeyPath:@"classTitle" cacheName:nil]; 

... à:

fetchedResultsController = [[NSFetchedResultsController alloc] 
              initWithFetchRequest:request 
              managedObjectContext:self.managedObjectContext 
              sectionNameKeyPath:nil cacheName:nil]; 

... et les sections vont disparaître. Sinon, la FRC créera une section pour chaque valeur de l'attribut classTitle dans le magasin. Si chaque instance myClass a une valeur différente pour classTitle, chaque instance aura sa propre section dans la tableview.

+0

C'était facile :) Merci TechZen! – Spindler

Questions connexes