2

Dans une application iPhone, je développe, j'attrape un ensemble de données d'un service Web, les stocke dans une matrice mutable pour les afficher dans un tableau et les stocke également dans des données de base en tant que sauvegarde. il n'y a pas de réseau.NSMutableArray devenant nul après reloadData

Mon tableau est initialisé en application: didFinishLaunchingWithOptions: comme suit
tableArray = [[NSMutableArray alloc] initWithCapacity:100];
le tableau est ensuite rempli après viewDidLoad est appelée, ce qui signifie la UITableView EXISTE (vérifié par le débogueur contrôle), et juste avant reloadData est appelé, je NSLog imprimer le contenu de la matrice, et bien sûr tout est là.

Mon problème est que après reloadData est appelé, tableArray devient null, comme indiqué par un NSLog dans tableView: numberOfRowsInSection :. Je ne comprends pas pourquoi cela se produit, même si je ne fais que programmer Cocoa depuis quelques mois et que je pourrais facilement manquer quelque chose d'évident.

EDIT: mise à jour avec le code de base.

@interface MyAppDelegate : NSObject {
...
NSMutableArray *tableArray;
}
@property (nonatomic, retain) NSMutableArray *tableArray;
...
@end

@implementation MyAppDelegate
@synthesize tableArray

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 
    tableArray = [[NSMutableArray alloc] initWithCapacity:100]; 

    masterViewController = [[MasterViewController alloc] initWithNibName:@"MasterViewController" bundle:[NSBundle mainBundle]]; 
    [masterViewController.tableView setDelegate:self]; 
    [masterViewController.tableView setDataSource:self]; 
    ... 
} 

Une méthode appelée runWithNetwork est alors appelé à viewDidLoad masterViewController:

- (void)runWithNetwork { 
    ... 
    NSArray *backpackArray = [[mainDict objectForKey:@"items"] objectForKey:@"item"]; 
    NSLog(@"%i", [backpackArray count]); 
    for (int a=0; a<[backpackArray count]; a++) { 
    NSDictionary *itemDict = [backpackArray objectAtIndex:a]; 
     NSString *ID = [[itemDict valueForKey:@"defindex"] stringValue]; 
     NSString *level = [[itemDict valueForKey:@"level"] stringValue]; 
     NSString *quality = [[itemDict valueForKey:@"quality"] stringValue]; 
     NSString *inventory = [[itemDict valueForKey:@"inventory"] stringValue]; 
     NSNumber *uid = [NSNumber numberWithInt:a]; 

     //Insert new 
     myItem = [NSEntityDescription insertNewObjectForEntityForName:@"Backpack" inManagedObjectContext:managedObjectContext_]; 
     [myItem setValue:level forKey:@"level"]; 
     [myItem setValue:inventory forKey:@"inventory"]; 
     [myItem setValue:quality forKey:@"quality"]; 
     [myItem setValue:uid forKey:@"uid"]; 

     //Link to item db 
     NSFetchRequest *fetch = [[NSFetchRequest alloc] init]; 
     NSPredicate *predicate = [NSPredicate predicateWithFormat:@"id == %@", ID]; 
     [fetch setEntity:[NSEntityDescription entityForName:@"GlobalItems" inManagedObjectContext:managedObjectContext_]]; 
     [fetch setPredicate:predicate]; 

     item = [[managedObjectContext_ executeFetchRequest:fetch error:nil] objectAtIndex:0]; 
     [myItem setValue:item forKey:@"item"]; 

     [tableArray addObject:[item valueForKey:@"name"]]; //a series of nsstrings 

    } 
    NSLog(@"%@, %i", tableArray, [tableArray retainCount]); // all strings are printed correctly here, retaincount is 1 

    [masterViewController.tableView reloadData]; 
} 

Puis je vais à mes méthodes de table:

- (NSInteger)tableView:(UITableView *)tView numberOfRowsInSection:(NSInteger)section { 
    NSLog(@"%@, %i", tableArray, [tableArray retainCount]); //(null) printed, 0 for retaincount 
    return [tableArray count]; //returns 0 
} 

La tableView se trouve dans le fichier xib de MasterViewController et y est liée correctement. Il est seulement décrit dans MasterViewController et est configuré comme un IBOutlet. tableArray est uniquement décrit dans MyAppDelegate.h et n'est pas recréé ailleurs.

+1

Il est très étrange que votre variable devient spontanément 'nil'. Avez-vous essayé d'exécuter votre programme avec Guard Malloc (menu Exécution -> Activer Guard Malloc) pour voir si vous avez un voerflow tampon quelque part? – zneak

+0

Essayé juste maintenant, et je suppose que quelque chose trouvé par GuardMalloc serait imprimé dans la console? Dans ce cas, tout va bien, je reçois les messages de bienvenue de GM, puis tout est imprimé par NSLog comme avant. – MattMcN

+1

Il y a quelques possibilités qui me viennent à l'esprit, mais il est difficile de trouver quelque chose avec une vague description de la façon dont le code fonctionne. Voir le code (ou une version réduite qui présente toujours le problème) faciliterait la déduction. – Chuck

Répondre

1

Comme je l'ai dit dans mon commentaire, il est difficile de comprendre ce qui ne va pas. Mais d'après mon expérience à aider les gens sur les listes de diffusion et autres, la cause la plus fréquente d'un tel bug est d'avoir deux objets différents quand vous pensez en avoir un. Par exemple, une instance est créée dans une plume et une autre est créée manuellement dans le code ailleurs. Cela pourrait valoir la peine d'être vérifié.

+0

Mis à jour avec du code.Re: bogues de duplication, tableView est seulement défini dans un fichier et est lié dans IB correctement, et tableArray est seulement défini dans un fichier et n'est pas recréé par accident dans tous les fichiers. Cependant, merci pour l'entrée, je n'avais pas encore vérifié plusieurs objets. – MattMcN

+0

@MattMcN: C'est la classe dont les méthodes retournent des résultats incohérents qui ont généralement le doppelganger. Dans ce cas, 'runWithNetwork' serait appelé sur une instance de la classe et la table enverrait ses méthodes de source de données à une autre. (Je n'essaie pas d'insister c'est ce qui ne va pas - juste que vous avez accidentellement négligé le suspect le plus probable.) – Chuck

+0

Aah, je vous comprends maintenant. La façon dont j'appelais runWithNetwork était '[[délégué [UIApplication sharedApplication]] runWithNetwork]' qui semble avoir retourné une nouvelle instance de mon délégué, une avec un tableau vide. J'ai maintenant re-architecturé l'application de délégué à viewController de nouveau à déléguer juste déléguer à viewController, et tout fonctionne grand. – MattMcN

1

Votre tableArray n'est pas conservé car vous n'utilisez pas votre accesseur pour le définir. Changer:

tableArray = [[NSMutableArray alloc] initWithCapacity:100]; 

à:

[self setTableArray:[[NSMutableArray alloc] initWithCapacity:100]]; 
Questions connexes