0

Update: Unfortunately the help offered below did not solve my problem of sharing a class property across functions. Can anyone else suggest a possible problem? Here's the latest code:

Header .h:

@interface FirstViewController:UIViewController <UITableViewDataSource, UITableViewDelegate, UITabBarControllerDelegate> {
 NSDictionary *sectorDictionary;
 NSInteger sectorCount;
}

@property (nonatomic, retain)  NSDictionary *sectorDictionary;

- (id)initWithData:(NSMutableDictionary*)inData;

Implementation .m:

@synthesize sectorDictionary;

- (id) testFunction:(NSDictionary*)dictionary {
 NSLog(@"Count #1: %d", [dictionary count]);
 return nil;
}

- (id)initWithData:(NSMutableDictionary *)inData {
 self = [self init];
 if (self) {
    [self testFunction:inData];
    // set the retained property
    self.sectorDictionary = inData;
  }

 return self;
}


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
 NSLog(@"Count #2: %d", [self.sectorDictionaryCopy count]);
 return [self.sectorDictionaryCopy count];
}

Console output:

2010-05-05 20:11:13.126 JSONApp[17378:207] Count #1: 9
2010-05-05 20:11:13.130 JSONApp[17378:207] Count #2: 0

Following up on this question about sharing an object between classes, I now need to figure out how to share that object across various functions in a class.

First, the setup: In my App Delegate I load menu information from JSON into a NSMutableDictionary and message that through to a view controller using a function called initWithData. I need to use this dictionary to populate a new Table View, which has methods like numberOfRowsInSection and cellForRowAtIndexPath.

I'd like to use the dictionary count to return numberOfRowsInSection and info in the dictionary to populate each cell. Unfortunately, my code never gets beyond the init stage and the dictionary is empty so numberOfRowsInSection always returns zero.

I thought I could create a class property, synthesize it and then set it. But it doesn't seem to want to retain the property's value. What am I doing wrong here?

In the header .h:

@interface FirstViewController:UIViewController <UITableViewDataSource, UITableViewDelegate, UITabBarControllerDelegate> {
    NSMutableDictionary *sectorDictionary;
    NSInteger sectorCount;
}

@property (nonatomic, retain)  NSMutableDictionary *sectorDictionary;

- (id)initWithData:(NSMutableDictionary*)data;

@end

in the implementation .m:

@synthesize sectorDictionary;

- (id) testFunction:(NSMutableDictionary*)dictionary {
    NSLog(@"Count #1: %d", [dictionary count]);    
    return nil;
}

- (id)initWithData:(NSMutableDictionary *)data {
    if (!(self=[super init])) {
        return nil;
    }
    [self testFunction:data];

    // this is where I'd like to set a retained property
    self.sectorDictionary = data;

    return nil;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    NSLog(@"Count #2: %d", [self.sectorDictionary count]);
    return [self.sectorDictionary count];
}

Output from NSLog:

2010-05-04 23:00:06.255 JSONApp[15890:207] Count #1: 9
2010-05-04 23:00:06.259 JSONApp[15890:207] Count #2: 0
Community
  • 1
  • 1
buley
  • 28,032
  • 17
  • 85
  • 106
  • 1
    It's a long shot, but because it is a mutable dictionary is there a chance something else is changing it? What happens if you make a `mutableCopy` instead? (i.e. `sectorDictionary = [data mutableCopy];`) – dreamlax May 05 '10 at 06:36
  • There's a typo in initWithData: You should return self, not nil. I'm sure in your real code it does because otherwise you would never see the second log message. – JeremyP May 05 '10 at 08:33
  • Very helpful. Will check this, report back and mark as answered if that's the ticket. Thank you! – buley May 05 '10 at 15:10
  • Unfortunately the return nil vs. return self did not clear up the issue. – buley May 06 '10 at 03:05
  • Where on earth is this `sectorDictionaryCopy` coming from? – Chuck May 06 '10 at 03:32
  • Sorry, added that as an extra test to see if it would work if I alloc'ed and init'd a different property. (I'm getting desperate; it also failed.) Forget it exists. I've edited the code back to normal. Sorry for the confusion. – buley May 06 '10 at 04:05

3 Answers3

0

Any init function should return self if it completes successfully. Change the return nil to return self at the end of initWithData.

-(id) initWithData:(NSMutableDictionary *)inData {
    self = [self init]; // best practice use super for method with same name
    if ( self ) {
        self.sectorDictionary = inData;
    }
    return self;
}

The sectorDictionary member should not be mutable. If it changes, you need to call reloadData on the table. Your setter function should make an immutable copy.

-(void) setSectorDictionary:(NSDictionary *)inData {
    NSDictionary *old = sectorDictionary;
    sectorDicitonary = inData ? [[NSDictionary alloc] intWithDictionary:inData] : nil;
    [self.table reloadData];
    [old release];
}
drawnonward
  • 53,459
  • 16
  • 107
  • 112
0

I believe your problem lies within the line self.sectorDictionary = data.

You need to firstly allocate some memory for the dictionary you are creating, so a line like self.sectorDictionary = [[NSMutableDictionary alloc] init]; is going to be necessary.

After you have initiated the new dictionary you need to populate it with the contents of the dictionary that was passed in.

So...

Try the line:

  self.sectorDictionary = [[NSMutableDictionary alloc] initWithDictionary:data];

instead of:

self.sectorDictionary = data;
-1

instead of

 self.sectorDictionary = data;

try this way...

self.sectorDictionary = [[NSMutableDictionary alloc] init];
self.sectorDictionary = (NSMutableDictionary *) data;
Mihir Mehta
  • 13,743
  • 3
  • 64
  • 88
  • Thanks for the answer. Unfortunately this gives me the same NSLog output as above (Count #1: 9; Count #2: 0) – buley May 05 '10 at 06:25
  • The cast is unnecessary and you've made a leak on the first line. – dreamlax May 05 '10 at 06:37
  • The answer is just wrong. You've added two things: a line which does nothing except leak memory, and a redundant cast. – dreamlax May 05 '10 at 09:00