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.
C'était facile :) Merci TechZen! – Spindler