2010-11-24 6 views
2

J'ai un problème avec la conservation des données dans un NSDictionary imbriqué. Ou est-ce quelque chose avec NSMutableDictionary qui fera ce travail? Jetez un coup d'oeil, je vais essayer d'expliquer aussi bien que possible.iPhone dev, NSDictionary comment retenir Dict complet?

Mon fichier .h ressemble:

@interface MyViewController : UIViewController 
<UITableViewDataSource, UITableViewDelegate> 
{ 
    NSDictionary *fullData; 
    IBOutlet UITableView *tableView; 
} 

@property (nonatomic, retain) NSDictionary *fullData; 
@property (nonatomic, retain) UITableView *tableView; 

@end 

Je mis mon INIT dans viewDidLoad

- (void)viewDidLoad { 
    ... 
    fullData = [NSDictionary dictionaryWithContentsOfURL:url]; 
    [fullData retain]; 
    [super viewDidLoad]; 
} 

Et cela fonctionne très bien lorsque je tente de l'insérer dans UITableViewCells et tout ce que je dois faire , même si je fais un NSLog qui imprime fullData ici, toutes les données seront affichées. comme ceci:

2010-11-24 14:49:53.334 MyApp[25543:40b] { 
    items =  (
       { 
      id = 5; 
      localId = 1; 
      name = "A name1"; 
     }, 
       { 
      id = 8; 
      localId = 3; 
      name = "A name2"; 
     }, 
       { 
      id = 9; 
      localId = 4; 
      name = "A name3"; 
     }, 
       { 
      id = 10; 
      localId = 5; 
      name = "A name4"; 
     }, 
       { 
      id = 11; 
      localId = 6; 
      name = "A name5"; 
     } 
    ); 
    results = 5; 
} 

Bien que cela fonctionne parfaitement, je veux garder le fullData dans mes autres événements, par exemple didSelectRowAtIndexPath. Tout d'abord, je dois conserver le, et si je le fais, seules les données de premier niveau seront conservées. les éléments dict vont juste pointer vers une mémoire qui n'existe pas.

J'essayer:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    NSLog(@"Data: %@", fullData); 
} 

Et cela renvoie parfois ceci:

2010-11-24 14:44:28.288 MyApp[25493:40b] Data: { 
    items =  (
     "<_NSIndexPathUniqueTreeNode: 0x9d2a820>", 
     "<CALayer: 0x9d27980>", 
     "<CALayer: 0x9d2bc30>", 
     "<CALayer: 0x9d29830>", 
     "<CALayer: 0x9d299e0>" 
    ); 
    results = 5; 
} 

Il semble que certaines valeurs sont conservées, mais les données contenues dans les articles ne sont pas possibles d'accès. Est-il préférable pour moi de stocker les données dans un fichier local, puis d'y accéder à nouveau, ou devrait-il être possible de conserver le dictionnaire complet?

J'ai essayé d'ajouter [[fullData objectForKey:@"items"] retain];

Je suis assez nouveau pour cela, donc je besoin d'aide pour faire mon code suivre les meilleures pratiques ainsi. J'ai essayé beaucoup de solutions et regardé plusieurs films d'Apple et d'autres endroits aussi. Je ne peux tout simplement pas le résoudre. Cela pourrait être simple mais je ne sais pas où chercher.

Merci.


Je suis désolé, j'ai résolu le problème moi-même je ne pas cette fonction,:

- (UITableViewCell *)tableView:(UITableView *)tableView 
     cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    NSLog(@"Retain count: %i", [fullData retainCount]); 
    UITableViewCell *cell = 
    [tableView dequeueReusableCellWithIdentifier:@"cell"]; 

    // create a cell 
    if(cell == nil) 
    { 
     cell = [[UITableViewCell alloc] 
       initWithStyle:UITableViewCellStyleDefault 
       reuseIdentifier:@"cell"]; 
    } 

    // fill it with content 
    NSArray *current = [[fullData objectForKey:@"items"] objectAtIndex:indexPath.row]; 
    NSString *rowLabel = [NSString stringWithFormat:@"%@, %@",[current valueForKey:@"localId"], [current valueForKey:@"name"]]; 
    cell.textLabel.text = rowLabel; 
    [current release]; 
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; 

    // return it 
    return cell; 
} 

Et la question est que je libère la variable actuelle chaque ligne de la table. Cela devrait être dû au fait que l'instance dans la variable current n'est pas une copie, mais plutôt la référence réelle.

Merci quand même.

Répondre

1

Vous aurez besoin de poster un peu plus de code pour localiser la solution. Le NSDictionary conserve son contenu, donc à moins que vous libérez les objets ailleurs, conserver NSDictionary suffira.

+0

J'ai changé le code pour ne plus utiliser Autorelease (fullData = [NSDictionary dictionaryWithContentsOfURL: url]; devient fullData = [[NSDictionary alloc] initWithContentsOfURL: url];) et le nombre de retain est toujours un dans le didSelectRowAtIndexPath. – Oldek

2
fullData = [NSDictionary dictionaryWithContentsOfURL:url]; 

est auto-libéré. vous ne devriez pas le retain. Utilisez ceci:

self.fullData = [[NSDictionary alloc] initWithContentsOfURL:url]; 

Et je ne pense pas que vous devez retain pour vos fins maintenant.Seulement si vous avez besoin d'y accéder aprèsMyViewController est publié.

Libérez-vous le UITableView? Il peut passer et libérer ses cellules qui sont dans votre code NSDictionary., je ne peux pas le dire.

+0

Le changement de code que vous avez recommandé fait la même chose que l'OP. Un objet libéré automatiquement ne vit que dans la portée où il a été créé. Ce qui signifie que, sans le conserver, il serait libéré après l'exécution de viewDidLoad. –

+0

@Robert, fixe-ish. –

0

Je suis désolé, j'ai résolu le problème moi-même je ne pas cette fonction,:

- (UITableViewCell *)tableView:(UITableView *)tableView 
     cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    NSLog(@"Retain count: %i", [fullData retainCount]); 
    UITableViewCell *cell = 
    [tableView dequeueReusableCellWithIdentifier:@"cell"]; 

    // create a cell 
    if(cell == nil) 
    { 
     cell = [[UITableViewCell alloc] 
       initWithStyle:UITableViewCellStyleDefault 
       reuseIdentifier:@"cell"]; 
    } 

    // fill it with content 
    NSArray *current = [[fullData objectForKey:@"items"] objectAtIndex:indexPath.row]; 
    NSString *rowLabel = [NSString stringWithFormat:@"%@, %@",[current valueForKey:@"localId"], [current valueForKey:@"name"]]; 
    cell.textLabel.text = rowLabel; 
    [current release]; 
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; 

    // return it 
    return cell; 
} 

Et la question est que je libère la variable actuelle chaque ligne de la table. Cela devrait être dû au fait que l'instance dans le courant de la variable n'est pas une copie, mais plutôt la référence réelle.

Merci quand même.

+1

N'utilisez pas ** retainCount **. Il est inutile pour le débogage. Aussi - éditez votre question et publiez ce code là. – bbum