Je travaille sur le Guide BNR de la programmation iOS, et j'ai du mal à essayer de résoudre un problème de division des données UITableView en sections. Le résumé de ce que j'ai fait est ceci. J'avais besoin d'un moyen flexible pour gérer les sections de la tableView, donc j'ai construit un NSMutableArray pour contenir les sections. Chaque objet dans le tableau représente une section de table via NSDictionary. Le dictionnaire a 2 clés, une chaîne pour l'en-tête de section et un tableau pour contenir les possessions de la section. J'ai une petite routine qui obtient tous les Possesions de la classe de magasin et les trie et les stocke dans les tableaux et le dictionnaire appropriés. J'ai travaillé à réécrire mon code pour l'incorporer et j'ai atteint un barrage routier confus. Comme mon application fonctionne dans le débogueur, je jette beaucoup de NSLogs pour suivre ce qui se passe. Je ne semble pas avoir de difficulté à accéder et à consigner le contenu de mon tableau de sections ou il est nsdictionaries de la plupart des méthodes de support pour la vue de la table; mais quand cellForRowAtIndexpath est appelé, les dieux du code arrêtent de sourire sur moi. D'une manière ou d'une autre, lorsque j'essaie d'accéder ou de déconnecter mon tableau de possessions, il est soudainement vide.Problème de source de données UITableView. Mon tableau de données est soudainement vide lorsque UITableView: cellForRowAtIndexPath: est appelé
Je ne peux pas pour la vie de moi comprendre cela. Cela fait maintenant un peu plus d'une journée que je me bats la tête et j'accepterais volontiers toute contribution ou aide. Ci-dessous est mes itemsViewController.h et l'implémentation. S'il vous plaît négliger le désordre des journaux et des sections commentées. J'ai essayé de comprendre cela et je les ai laissés afin que les gens puissent me dire ce que je devrais changer à propos de mon approche. Aussi, il peut être utile de noter que la table est initialement vide et l'application n'a aucun problème jusqu'à ce que j'essaie d'ajouter quelque chose.
//
// ItemsViewController.h
// HomePwnr
#import <Foundation/Foundation.h>
#import "ItemDetailViewController.h"
@interface ItemsViewController : UITableViewController
{
NSMutableArray *sections; // variable to hold the number of sections
}
-(void)addNewPossession:(id)sender;
-(void)divideSections;
@end
Voici la mise en œuvre
//
// ItemsViewController.m
// HomePwnr
#import "ItemsViewController.h"
#import "PossessionStore.h"
#import "Possession.h"
@implementation ItemsViewController
- (id) init
{
NSLog(@"ItemsViewController init called");
// Call the superclass's designated initializer
self = [super initWithStyle:UITableViewStyleGrouped];
if (self) {
// create a new barItem that will send addNePossession: to itemsViewController
UIBarButtonItem *bbi = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addNewPossession:)];
// Set this barButtonItem as the right item in the Navigation item
[[self navigationItem] setRightBarButtonItem:bbi];
//The Navigation item retains its buttons so release bbi
[bbi release];
// set the title of the navigation item
[[self navigationItem] setTitle:@"Homepwner"];
//[[self navigationItem] setLeftBarButtonItem:[self editButtonItem]];
}
sections = [[[NSMutableArray alloc] init] retain]; // added the extra retain here to make sure my sections weren't getting released pre maturely
// set up sections here by dividing allPossessions
[self divideSections];
return self;
}
- (id) initWithStyle:(UITableViewStyle)style
{
return [self init];
}
-(void)divideSections
{
NSLog(@"divideSections called");
// For simplicity we'll just empty out the sections array and rebuild it each time we add or modify a possesion
[sections removeAllObjects];
NSArray *cheapStuff = [[NSArray alloc] initWithArray:[[PossessionStore defaultStore] possesionsFromPredicate:@"valueInDollars < 50"]];
NSArray *expensiveStuff = [[NSArray alloc] initWithArray:[[PossessionStore defaultStore] possesionsFromPredicate:@"valueInDollars >= 50"]];
// we'll be making an NSDictionary for each section. it will hold an array of possesions for each section and it's key will serve as the sections header
if ([cheapStuff count] > 0) {
NSMutableDictionary *section1 = [NSMutableDictionary dictionaryWithObject:cheapStuff forKey:@"Possessions"];
[section1 setValue:@"Cheap Stuff" forKey:@"Header"];
[sections addObject:section1];
// sections now retains NSDictionary so we release it
[section1 release];
}
if ([expensiveStuff count] > 0) {
NSMutableDictionary *section2 = [NSMutableDictionary dictionaryWithObject:expensiveStuff forKey:@"Possessions"];
[section2 setValue:@"Cheap Stuff" forKey:@"Header"];
[sections addObject:section2];
// sections now retains NSDictionary so we release it
[section2 release];
}
//now our arrays are retained by the dictionarys so we release them
[cheapStuff release];
[expensiveStuff release];
NSLog(@" End of divideSections sections holding %@", sections);
}
/*
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
ItemDetailViewController *detailViewController = [[[ItemDetailViewController alloc] init] autorelease];
// NSArray *possessions = [[PossessionStore defaultStore] allPossessions];
// give the detail view controller a pointer to the possesion object in row
// get the NSDictionary located at the section index, get the dictionary's array, get the possession at row index
Possession *p = [[[sections objectAtIndex:[indexPath section]] objectAtIndex:0] objectAtIndex:[indexPath row]];
[detailViewController setPossession:p];
// push it onto the navigationControllers stack
[[self navigationController] pushViewController:detailViewController animated:YES];
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
////If the table view is asking to commit the delete command
if (editingStyle == UITableViewCellEditingStyleDelete) {
//PossessionStore *ps = [PossessionStore defaultStore];
// NSArray *possessions = [ps allPossessions];
// Possession *p = [possessions objectAtIndex:[indexPath row]];
int section = [indexPath section];
int row = [indexPath row];
Possession *p = [[[sections objectAtIndex:section] objectAtIndex:0] objectAtIndex:row];
[[[PossessionStore defaultStore] allPossessions] removePossession:p];
// remove the row from the table view with an animation
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:YES];
}
}
-(void) tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath{
[[PossessionStore defaultStore] movePossessionAtIndex:[sourceIndexPath row] toIndex:[destinationIndexPath row]];
}
*/
-(void)addNewPossession:(id)sender
{
//
NSLog(@"addNewPossession called - sections = %@", sections);
[[PossessionStore defaultStore] createPossession];
//NSLog(@"Possesion store now holds %@", [[PossessionStore defaultStore] allPossessions]);
//we've added a new possession so we'll divide out the sections again
[self divideSections];
//NSLog(@"addNewPossession exiting - sections = %@", sections);
//tableview returns the tablesview
[[self tableView] reloadData];
//NSLog(@"table view reloading data - sections = %@", sections);
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
int numSections = [[(NSArray *)[sections objectAtIndex:section] objectForKey:@"Possessions"] count];
//NSLog(@"numberOfRowsInSection: called for section %i, returning %i.", section, numSections);
return numSections;
}
- (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView
{
NSLog(@"returning number of sections: %i", [sections count]);
// return the count of the sections array
return [sections count];
}
- (NSString *) tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
NSLog(@"tableView:titleForHeaderInSectionCalled - sections = %@", sections);
//Configure the header titles based on the number of sections
if ([sections count] <= 1) {
// return simple title for only one section in table
NSLog(@"Returning My Stuff");
return @"My Stuff";
} else {
NSLog(@"The header returned is %@", [[sections objectAtIndex:section] objectForKey:@"Header"]);
// or return the key for the dictionary entry for the current section
return [[[sections objectAtIndex:section] objectAtIndex:section] objectForKey:@"Header"];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"tableView:cellForRowAtIndexPath called for section %d, Row %d", [indexPath section], [indexPath row]);
NSLog(@"Sections = %@", sections);
NSLog(@"The Dictionary is %@", [sections objectAtIndex:[indexPath section]]);
//NSLog(@"thisSection array should be %@", (NSArray *)[[sections objectAtIndex:thisSection] objectForKey:@"Possessions"]);
//NSArray *thisSectionArray = [[sections objectAtIndex:thisSection] objectForKey:@"Possessions"];
// Check for reusable cell
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell"];
// If there is no cell of this type create a new one
if (!cell) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"UITableViewCell"] autorelease];
}
// get the NSDictionary located at the section index, get the dictionary's array, get the possession at row index
//Possession *p = [thisSection objectAtIndex:[indexPath row]];
//[[cell textLabel] setText:[p description]];
[[cell textLabel] setText:@"cell text"];
return cell;
}
-(void)viewWillAppear:(BOOL)animated
{
[self divideSections];
[super viewWillAppear:YES];
NSLog(@"viewWillAppear called - sections = %@", sections);
}
-(void)viewDidUnload
{
[super viewDidUnload];
NSLog(@"viewDidUnload called - sections = %@", sections);
}
@end
Enfin voici mon journal d'essayer d'exécuter l'application. Le petit indicateur vert est assis juste sur la ligne où j'essaie d'enregistrer le contenu des sections pendant cellForRow ....... après le plantage de l'application.
2012-03-10 06:22:00.177 HomePwnr[44399:f803] ItemsViewController init called
2012-03-10 06:22:00.180 HomePwnr[44399:f803] divideSections called
2012-03-10 06:22:00.181 HomePwnr[44399:f803] End of divideSections sections holding (
)
2012-03-10 06:22:00.188 HomePwnr[44399:f803] divideSections called
2012-03-10 06:22:00.189 HomePwnr[44399:f803] End of divideSections sections holding (
)
2012-03-10 06:22:00.189 HomePwnr[44399:f803] returning number of sections: 0
2012-03-10 06:22:00.190 HomePwnr[44399:f803] returning number of sections: 0
2012-03-10 06:22:00.191 HomePwnr[44399:f803] viewWillAppear called - sections = (
)
2012-03-10 06:22:04.234 HomePwnr[44399:f803] addNewPossession called - sections = (
)
2012-03-10 06:22:04.235 HomePwnr[44399:f803] divideSections called
2012-03-10 06:22:04.237 HomePwnr[44399:f803] End of divideSections sections holding (
{
Header = "Cheap Stuff";
Possessions = (
"Shiny Gun (7R3K0): Worth $40, recorded on 2012-03-10 11:22:04 +0000"
);
}
)
2012-03-10 06:22:04.238 HomePwnr[44399:f803] returning number of sections: 1
2012-03-10 06:22:04.239 HomePwnr[44399:f803] tableView:titleForHeaderInSectionCalled - sections = (
{
Header = "Cheap Stuff";
Possessions = (
"Shiny Gun (7R3K0): Worth $40, recorded on 2012-03-10 11:22:04 +0000"
);
}
)
2012-03-10 06:22:04.240 HomePwnr[44399:f803] Returning My Stuff
2012-03-10 06:22:04.241 HomePwnr[44399:f803] tableView:titleForHeaderInSectionCalled - sections = (
{
Header = "Cheap Stuff";
Possessions = (
"Shiny Gun (7R3K0): Worth $40, recorded on 2012-03-10 11:22:04 +0000"
);
}
)
2012-03-10 06:22:04.241 HomePwnr[44399:f803] Returning My Stuff
2012-03-10 06:22:04.243 HomePwnr[44399:f803] tableView:cellForRowAtIndexPath called for section 0, Row 0
(lldb)
Quelqu'un a des conseils? – vichudson1