2010-11-24 5 views
2

Ich habe ein Problem mit dem Zurückhalten von Daten in einem verschachtelten NSDictionary. Oder ist es etwas mit NSMutableDictionary, dass dies funktioniert? Schau mal, ich werde versuchen es so gut wie möglich zu erklären.iPhone dev, NSDictionary Wie behält man das volle Dict?

Meine .h-Datei wie folgt aussieht:

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

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

@end 

ich meine inits in viewDidLoad

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

einrichten Und das funktioniert gut, wenn ich versuche, es in UITableViewCells einfügen und was ich tun muss Auch wenn ich einen NSLog mache, der fullData hier ausgibt, werden alle Daten angezeigt. wie so:

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; 
} 

Obwohl diese perfekt funktioniert Ich will die freie Entfaltung vonDaten in meinen anderen Veranstaltungen halten, zum Beispiel DidSelectRowAtIndexPath. Zuallererst muss ich das beibehalten, und wenn ich das tue, werden nur die Daten der ersten Ebene beibehalten. Die dict-Elemente zeigen nur auf einen Speicher, der nicht existiert. So

Ich versuche:

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

Und manchmal gibt diese:

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

Es scheint, wie einige Werte beibehalten werden, jedoch sind die Daten innerhalb Elemente sind nicht möglich, den Zugang. Ist es für mich besser, die Daten in einer lokalen Datei zu speichern und dann zu diesem Zeitpunkt wieder darauf zuzugreifen, oder sollte es möglich sein, das vollständige Wörterbuch zu behalten?

Ich versuchte [[fullData objectForKey:@"items"] retain];

Ich bin ziemlich neu in diesem hinzufügen, so dass ich Hilfe brauche, um meinen Code folge Best Practices sowie zu machen. Ich habe viele Lösungen ausprobiert und mehrere Filme von Apple und anderen Orten gesehen. Ich kann es einfach nicht lösen. Es könnte einfach sein, aber ich weiß nicht, wo ich suchen soll.

Vielen Dank.


Es tut mir leid, ich habe mich um das Problem zu lösen ich diese Funktion nicht enthalten:

- (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; 
} 

Und das Problem ist, dass ich die aktuelle Variable jede Zeile in der Tabelle freigeben. Dies sollte darauf zurückzuführen sein, dass die Instanz in der Variablen current keine Kopie ist, sondern die reale Referenz.

Danke trotzdem.

Antwort

1

Sie müssen etwas mehr Code posten, um die Lösung zu finden. Das NSDictionary behält seinen Inhalt bei. Wenn Sie also die Objekte nicht zu weit freigeben, reicht es aus, das NSDictionary beizubehalten.

+0

Ich habe den Code geändert, so dass ich nicht mehr Autorelease (FullData = [NSDictionaryWithContentsOfURL: URL]; FullData = [[NSDictionary Alloc] InitWithContentsOfURL: URL];) und die Retain-Anzahl ist immer noch eine in der didSelectRowAtIndexPath. – Oldek

2
fullData = [NSDictionary dictionaryWithContentsOfURL:url]; 

wird automatisch freigegeben. Sie sollten nicht retain es. Verwenden Sie diese Option:

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

Und ich glaube nicht, dass Sie es für Ihre Zwecke jetzt retain müssen.Nur wenn Sie darauf zugreifen müssen, wird nachMyViewController freigegeben.

Sie veröffentlichen die UITableView? Es kann gehen und geben Sie es Zellen, die in Ihrem NSDictionary. W/o mehr Code sind, kann ich nicht sagen.

+0

Die von Ihnen empfohlene Codeänderung entspricht der Vorgehensweise des OP. Ein automatisch freigegebenes Objekt lebt nur in dem Bereich, in dem es erstellt wurde. Das bedeutet, dass es ohne den Retain irgendwann nach der Ausführung von viewDidLoad freigegeben würde. –

+0

@Robert, fixed-ish. –

0

Es tut mir leid, ich habe mich um das Problem zu lösen ich diese Funktion nicht enthalten:

- (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; 
} 

Und das Problem ist, dass ich die aktuelle Variable jede Zeile in der Tabelle freigeben. Dies sollte darauf zurückzuführen sein, dass die Instanz in der Variablen current keine Kopie ist, sondern die reale Referenz.

Danke trotzdem.

+1

Verwenden Sie nicht ** retainCount **. Es ist nutzlos für das Debuggen. Außerdem - bearbeite deine Frage und poste diesen Code dort. – bbum