views:

1008

answers:

8

I'm trying to use a UITableViewController (delegate & dataSource for the view) to display a simple table read from a Plist. The Plist contains a NSDictionary which itself contains several NSDictionary objects that represent objects used in my application.

The rest of the code looks something like this (simplified):

- (void)viewDidLoad {
    [super viewDidLoad];
    [self loadObjectsFromPlist];
}

- (void)loadObjectsFromPlist {
    NSString *objectPlistFile = [[NSBundle mainBundle] pathForResource:@"Objects" ofType:@"plist"];
    NSDictionary *objectsDictionary = [NSDictionary dictionaryWithContentsOfFile:objectsPlistFile];

    objects = [[NSMutableArray alloc] init];
    NSEnumerator *objectEnumerator = [objectsDictionary objectEnumerator];
    NSDictionary *objectData;
    while(objectData = [objectEnumerator nextObject]) {
        [objects addObject:[MyObject objectFromDictionary:objectData]];
    }
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [objects count];
}

As I'm not using any sections I return 1 in numberOfSectionsInTableView of the controller.

The objectFromDictionary method of "MyObject" assigns the data read from the NSDictionary to a new object. I tried retaining, copying etc. too, but that didn't change anything.

I get a EXC_BAD_ACCESS in tableView:numberOfRowsInSection when calling [objects count]. I tried using the Object Allocation Instrument, but I didn't find a problem. My Plist currently contains only data for one object. The Debugger displays "1 objects" in red color for the objects attribute, so I think this is related to the problem.

A: 

It sounds like it is calling numberOfRowsInSection before loadObjectsFromPlist is being called.

If you are loading your controller programatically, maybe try calling loadObjectsFromPlist from initWithFrame:Style: instead of viewDidLoad.

If I had a mac in front of me i'd do it myself, but you might want to try setting break points and figuring out in what order these methods are being called. NSLog statements all over the palce also work.

Jon Swanson
I already checked this with the debugger. Like said before the debugger even displays the data loaded from the Plist (although in red).
Koraktor
+1  A: 

If the debugger shows that the EXC_BAD_ACCESS occurs at [servers count], is the (assumed) ivar servers being initialized properly? I didn't find any reference to it in your sample code.

craig
Oh, I'm sorry. I forgot to rename that in my text. I tried to reduce the code to a minimum and also changed variable names to be more general. In my real project the variable is calles `servers` but it's initialized like `objects` in my question's code example.
Koraktor
+1  A: 

To ensure that data is loaded at the appropriate time, try lazy initialization:

- (NSArray *)objectsFromPlist {
    if (!objects) {
       ... // initialize once here
    }
    return objects;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [[self objectsFromPlist] count];
}
dbarker
+1  A: 

What is objects? Can you show your header file? It might give me a better understanding. Also, have you tried putting [super viewDidLoad] after your [self loadObjectsFromPlist]? It seems like a timing issue, or objects is getting released on accident in one of your methods.

Jab
No, I already tried this. Still crashes.
Koraktor
Try skipping your plist load and just put objects = [[NSMutableArray alloc] init]; before the [super viewDidLoad]. If that resolves it, then that confirms there is a timing issue going on.
Jab
This works. But how can I really resolve this?
Koraktor
is object a property? I'm wondering if object is actually getting retained properly. Try changing the alloc line in your plist function to objects = [[[NSMutableArray alloc] init]retain];
Jab
A: 

It's possible that you've deallocated your UITableViewController, meaning that the objects member is no longer valid. Make sure that you're holding a reference to the UITableViewController somewhere. An easy way to check to see if this is the case is to add a [self retain] call in your viewDidLoad method (temporarily!). If that makes the problem go away, then you need to double-check who owns the controller and ensure they haven't released it.

EDIT: I guess a better way to test would be to put a breakpoint in your dealloc method.

Jesse Rusak
That didn't work. Still crashes with [self retain] in viewDidLoad.
Koraktor
I added a breakpoint to the dealloc of my objects... it's never called.
Koraktor
+1  A: 

My guess is that you may have to post your entire (relevant) code, not a stripped down version. Without knowing what else you may be doing, both in the code and the plist, it's going to be hard to nail this down... we're all just firing blindly here (admittedly not an unusual occurrence on SO ;-)

Ben Gottlieb
This would probably have solved my problem faster. I'll try to remember this. ;)
Koraktor
A: 

Put your [self loadObjectsFromPlist] before [super viewDidLoad]. Your "objects" variable is never initialized which is why you get a EXEC_BAD_ACCESS error.

Mugunth Kumar
This was already mentioned by Jesse Brown before and didn't work.
Koraktor
A: 

Ok, after reading through all your answers and trying to find my error, I almost compeletely rewrote my code. Finally, I removed debug output I added when the error occured for the first time.

NSLog(@"Object count: %@", [objects count]);

As NSArray's count doesn't return an object but an integer this is obviously wrong and should have been:

NSLog(@"Object count: %u", [objects count]);

Nevertheless the EXC_BAD_ACCESS occured without this line before, but it seems it slowed down my debugging. ;) Sadly, I am not able to reproduce the real problem now.

What I can say: The error was not the result of a timing problem. I double checked this now.

Koraktor
When you get a EXC_BAD_ACCESS, go to the console and type "bt" to get a stack trace. could be useful for you and also for people trying to help you.
siukurnin