1

I have created an app which is approved by apple and currently buyable in the appstore. But after the 4.3 update it crashes when scrolling the UITableView with the EXC_BAD_ACCESS error. NSZombieEnabled = YES, will get the app working again but this isn't a solution of course ;) The error is reported in the Main class on the following line:

int retVal = UIApplicationMain(argc, argv, nil, nil);

Also the stacktrace doesn't help me out either:

> #0  0x00faf09f in objc_msgSend ()
> #1  0x04c7b9e0 in ?? ()
> #2  0x00d6004c in CFRelease ()
> #3  0x00e42369 in -[__NSArrayM removeObjectAtIndex:] ()
> #4  0x00e3dcfc in -[NSMutableArray removeObjectsInRange:] ()
> #5  0x003507a5 in -[UITableView(_UITableViewPrivate) _updateVisibleCellsNow:] ()
> #6  0x0034890c in -[UITableView layoutSubviews] ()
> #7  0x01d80a5a in -[CALayer layoutSublayers] ()
> #8  0x01d82ddc in CALayerLayoutIfNeeded ()
> #9  0x01d280b4 in CA::Context::commit_transaction ()
> #10 0x01d29294 in CA::Transaction::commit ()
> #11 0x01d2946d in CA::Transaction::observer_callback ()
> #12 0x00e2a89b in __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__
> ()
> #13 0x00dbf6e7 in __CFRunLoopDoObservers ()
> #14 0x00d87857 in CFRunLoopRunSpecific ()
> #15 0x00d87761 in CFRunLoopRunInMode ()
> #16 0x017371c4 in GSEventRunModal ()
> #17 0x01737289 in GSEventRun ()
> #18 0x002dec93 in UIApplicationMain ()
> #19 0x000026d4 in main (argc=1, argv=0xbffff068) at
> /Users/geoffrey/Documents/iPhone
> projecten/Xcode Projecten/HU
> Rooster/main.m:14

Can someone please help me out with this? I'm trying to get this working for 2 days now :(

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Cell";

    CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:self options:nil];
        cell = customCell;
        self.customCell = nil;
    }
    int num = indexPath.row;

    if (indexPath.section != 0) {
        for (int i=1; i <= indexPath.section; i++) {
            num = (num + [[sectorSize objectAtIndex:(i-1)] intValue]);
        }
    }
    // Configure the cell...
        cell.tijdLabel.text = [NSString stringWithFormat:@"%@ - %@", [tijdBeginList objectAtIndex:num], [tijdEindList objectAtIndex:num]];
        cell.lesVormLabel.text = [lesVormList objectAtIndex:num];
        cell.docentLabel.text = [docentList objectAtIndex:num];
        cell.lokaalLabel.text = [lokaalList objectAtIndex:num];
        cell.opmerkingLabel.text = [opmerkingList objectAtIndex:num];
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
    return cell;
}
  • Almost certainly a memory problem (something should have been retained more!) - can you post the code from the controller that is your UITableView's dataSource please? – deanWombourne Mar 14 '11 at 15:04
  • Take a look at my updated answer, it might contain the solution. – Erik B Mar 15 '11 at 12:43
  • Updated my answer one more time. I felt like I've put to much effort into this to just give up. I hope it helps. – Erik B Mar 15 '11 at 22:31

7 Answers7

6

Check the dealloc method of your Custom Cell implementation and make sure [super dealloc] is the last instruction. I had a similar issue and it turned out I had it calling [super dealloc] before it was releasing some view labels and other items.

cthomaschase
  • 108
  • 1
  • 6
0

These lines

> #3  0x00e42369 in -[__NSArrayM removeObjectAtIndex:] ()
> #4  0x00e3dcfc in -[NSMutableArray removeObjectsInRange:] ()
> #5  0x003507a5 in -[UITableView(_UITableViewPrivate) _updateVisibleCellsNow:] (

Give me a hunch that the problem is in the cells you are creating at cellForRowAtIndexPath selector. Something might end up being over released.

Pacu
  • 1,985
  • 20
  • 33
0

Something is being over released and from the look of the stack trace it seems to be a UITableViewCell that is being released one too many times.

You say that NSZombieEnabled = YES keeps it running, which actually surprises me. What NSZombie does, at least when I've been using it, is that it tells you what deallocated object was sent what message, but the application still crashes.

To further help you it would be helpful if you could provide the output from NSZombie as well as your implementation of:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

EDIT: I've never used the interface builder, but I found a line that I found suspicious:

self.customCell = nil;

If the customCell property is a retain property, that line will release the custom cell. Try changing that property to an assign property.

The difference might be that

[[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:self options:nil];

used to retain the custom cell in previous versions, but doesn't in 4.3. You should figure it out, so that you're not leaking in older versions. Drop a comment if you need more help.

EDIT 2: Ok, so I have one more idea.

You could check the retain count of the cell:

NSLog(@"Retain count: %i", [cell retainCount]);

You could check the retain count in different places and compare it between 4.3 and prior versions. Maybe that way you could figure out what have changed.

I also read the documentation for loadNibNamed:owner:options: and found the following that might be relevant:

(To establish outlet connections, this method uses the setValue:forKey: method, which may cause the object in the outlet to be retained automatically.)

The documentation says that the object may be retained, so I guess that's a behavior that might change between versions.

Erik B
  • 40,889
  • 25
  • 119
  • 135
  • NSZombieEnabled = YES doesn't change anything to my debugger output, it just keeps it running. Keep in mind that the app worked in previous iOS versions and is approved by Apple, i didn't change anything in my code and now on iOS 4.3 it crashes with the EXC_BAD_ACCES Error. – Geoffrey Mastenbroek Mar 14 '11 at 17:33
  • Added the implementation of cellForRowAtIndex in my original message. – Geoffrey Mastenbroek Mar 14 '11 at 17:36
  • First, Thanx for your reply! changing the property of customCell to assign doesn't change anything, also no changes in debugger output. Also removing the self.customCell = nil; line gives no changes. Also putted a breakpoint on this line and didn't crash at this line, it crashes when i scroll thru the TableView and the method cellForRowAtIndexPath is looped once (but can't find the method it enters after this one). – Geoffrey Mastenbroek Mar 15 '11 at 16:01
  • The problem as far as I can tell is that when the cell is returned by cellForRowAtIndexPath its retain count is too low or it has been autoreleased too many times. The other possibility is that Apple introduced a bug in 4.3, but it might just be that you were relying on undocumented behavior that now have changed. – Erik B Mar 15 '11 at 22:38
  • 2
    `-retainCount` should never be used for debugging. Its returned value is all but useless. See here for more: http://stackoverflow.com/questions/4636146/when-to-use-retaincount/4636477#4636477 – Brad Larson Mar 15 '11 at 22:41
  • @Brad Larson The point here is to find the difference in behavior between 4.3 and prior versions. For that I think using retainCount is perfectly fine. I agree that debugging with retainCount can be tricky, but it's not useless, it has actually helped me figure out bugs in the past. – Erik B Mar 15 '11 at 22:55
0

Your mistake is that you are assigning the cell pointer to the customCell pointer, then setting the customCell to nil, meaning cell will be pointing to a non-valid object.

Use cell = [[customCell copy] autorelease]; instead and you should be good to go.

Rog
  • 18,602
  • 6
  • 76
  • 97
  • Setting `customCell` to nil doesn't set `cell` to nil, so that's just wrong, but copying the `customCell` is still worth a try. – Erik B Mar 16 '11 at 13:30
  • Close; cell is not going to be pointing to nil. it'll be pointing to garbge. – bbum Mar 16 '11 at 16:04
0

First, you are reading the stack trace backwards. The crash is in [__NSArrayM removeObjectAtIndex:] (or just below).

Secondly, the problem indicates an object was created, put into an array, and then released to the point of deallocation while the array still held onto it. This is an all too common over-release problem.

Here:

    [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:self options:nil];
    cell = customCell;
    self.customCell = nil;

You grab a reference to the customCell and then promptly release it. The only reason why it likely sticks around is because NIB loading probably retained/autoreleased the object on load.

Rog's suggestion of retain/autoreleasing the cell is a good one.

But there is a bigger problem; you are loading a nib in the middle of trying to draw a table view.

Loading a NIB is a relatively glacially slow operation to be doing in the middle of something as performance sensitive as drawing a table. It is quite likely that your app's scrolling and/or user interaction is going to be "clunky" because of this.

While cell = [[customCell retain] autorelease]; might fix the crash, I would suggest that you also refactor the code to not do something so expensive during table rendering.

bbum
  • 162,346
  • 23
  • 271
  • 359
0

I was getting same issue ...

in cellForRowAtIndexPath:(NSIndexPath *)indexPath

Check your CellIdentifier with CellIdentifier of xib file ...

Ravi Chokshi
  • 1,106
  • 9
  • 18
0

make your CellIdentifier = @"CustomCell"

This will fix your issue

Ravi Chokshi
  • 1,106
  • 9
  • 18