Search code examples
iphoneiosnsdictionarynsmutabledictionaryretain

iPhone dev, NSDictionary how to retain full Dict?


I have a problem with retaining data in a nested NSDictionary. Or is it something with NSMutableDictionary that will make this work? Take a look, I will try to explain as good as possible.

My .h file looks like:

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

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

@end

I set up my inits in viewDidLoad

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

And this works fine when I try to insert it into UITableViewCells and whatever I need to do, even if I do an NSLog that prints fullData here, all of the data will be displayed. like 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;
}

Although this works perfectly I want to keep the fullData in my other events, for example didSelectRowAtIndexPath. First of all, I have to retain the , and also if I do, only the first level data will be retained. the dict items will just point to some memory which doesn't exist.

So I try:

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

And this sometimes returns this:

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

It seems like some values are retained, however the data inside items are not possible to access. Is it better for me to store the data to a local file and then access it again at this point, or should be it possible to retain the full dictionary?

I tried adding [[fullData objectForKey:@"items"] retain];

I am pretty new to this, so I need help to make my code follow best practices as well. I have tried many solutions and watched several movies from apple and other places too. I just can't solve it. It might be simple but I dont know where to look.

Thank you.


I am sorry, I did solve the issue myself I didn't include this function:

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

And the issue is that I release the current variable each row in the table. This should be a result of that the instance in the variable current is not a copy, instead it is the real reference.

Thanks anyways.


Solution

  • You'll need to post some more code in order to track down the solution. The NSDictionary retains its contents, so unless you are over-releasing the objects somewhere else, retaining the NSDictionary will be sufficient.