6

Thank you in advance for any help/insight you can give into the issue I am having. Just recently my iOS app began to fail with the dreaded EXC_BAD_ACCESS error. I did a lot of research on SO and Google and received some great advice, but none of the posts have helped me to resolve my issue. By now, I understand that EXC_BAD_ACCESS could be one of two things:

1) A pointer is now pointing to memory that was deallocated.
2) A pointer itself is corrupt.

I read and followed the instructions here, here, here, and here. When I perform "Build and Run" I can reproduce the exc_bad_access 100% of the time. However, when I enabled NSZombie in either the debugger or in Instruments, I never can reproduce the issue. Furthermore, NSZombie does not leave any helpful information in the console.

The closest I got to pinpointing the issue was by literally putting an NSLog after every single line of code, in order to see where it was crashing. I believe that it is crashing at two distinct points - both of which are returning a cell in the cellForRowAtIndexPath. Below I'm providing the two methods where I believe things are crashing, as well as the error output on my console. Any help or guidance would be greatly appreciated, thanks!

The offending method:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 0) {
    static NSString *CellIdentifier = @"EventDetailCell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if (cell == nil)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
        cell.textLabel.textColor = [UIColor colorWithRed:150 green:143 blue:135 alpha:1.0];
        cell.textLabel.highlightedTextColor = [UIColor whiteColor];
        cell.textLabel.font = [UIFont fontWithName:@"Helvetica" size:15];

        if (indexPath.row < 4) {
            UIImageView *disclosureArrow = [[UIImageView alloc] initWithFrame:CGRectMake(280, 15, 10, 14)];
            disclosureArrow.image = [UIImage imageNamed:@"tableRowAccessoryArrow"];
            [cell.contentView addSubview:disclosureArrow];
        }
    } else {
        if ((indexPath.section == 0) && (indexPath.row == 4)) {
            for (UIView *v in [cell.contentView subviews]) {
                [v removeFromSuperview];
            }
        }
    }

    switch (indexPath.row) {
        case 0:
            cell.textLabel.text = [NSString stringWithFormat:@"%@", self.startTime];
            cell.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"eventDetailRowTop"]];
            cell.imageView.image = [UIImage imageNamed:@"clockIcon"];
            break;
        case 1:
            cell.textLabel.text = @"Location";
            cell.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"eventDetailRowMiddle"]];
            cell.selectedBackgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"eventDetailRowMiddleSelected"]];
            cell.imageView.image = [UIImage imageNamed:@"mapIcon"];
            break;
        case 2:
            cell.textLabel.text = [NSString stringWithFormat:@"%u attendees", [self.attendees count]];
            cell.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"eventDetailRowMiddle"]];
            cell.selectedBackgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"eventDetailRowMiddleSelected"]];
            cell.imageView.image = [UIImage imageNamed:@"attendeesIcon"];
            break;
        case 3:
            cell.textLabel.text = [NSString stringWithFormat:@"%u fomos", [self.fomos count]];
            cell.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"eventDetailRowBottom"]];
            cell.selectedBackgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"eventDetailRowMiddleSelected"]];
            cell.imageView.image = [UIImage imageNamed:@"fomoIcon"];
            break;
        case 4:
        {
            cell.selectionStyle = UITableViewCellSelectionStyleNone;

            UIImage *clockIcon = [UIImage imageNamed:@"clockIcon"];
            UIImageView *iconSlot = [[UIImageView alloc] initWithFrame:CGRectMake(3, 18, 18, 18)];
            iconSlot.image = clockIcon;
            [cell.contentView addSubview:iconSlot];

            NSString *currentTime = @"Happening Now";
            UILabel *currentTimeLabel = [[UILabel alloc] initWithFrame:CGRectMake(25, 8, 150, 36)];
            currentTimeLabel.backgroundColor = [UIColor clearColor];
            currentTimeLabel.textColor = [UIColor whiteColor];
            currentTimeLabel.font = [UIFont fontWithName:@"Helvetica" size:14];
            currentTimeLabel.text = currentTime;
            [cell.contentView addSubview:currentTimeLabel];

            UIImage *listView = [UIImage imageNamed:@"listViewSelected"];
            self.listViewButton = [UIButton buttonWithType:UIButtonTypeCustom];
            self.listViewButton.frame = CGRectMake(180, 8, 36, 36);
            self.listViewButton.tag = 1;
            [self.listViewButton addTarget:self action:@selector(togglePhotosView:) forControlEvents:UIControlEventTouchUpInside];
            [self.listViewButton setBackgroundImage:listView forState:UIControlStateNormal];
            [cell.contentView addSubview:self.listViewButton];

            UIImage *gridView = [UIImage imageNamed:@"gridViewIcon"];
            self.gridViewButton = [UIButton buttonWithType:UIButtonTypeCustom];
            self.gridViewButton.frame = CGRectMake(240, 7.2f, 36, 36);
            self.gridViewButton.tag = 2;
            [self.gridViewButton addTarget:self action:@selector(togglePhotosView:) forControlEvents:UIControlEventTouchUpInside];
            [self.gridViewButton setBackgroundImage:gridView forState:UIControlStateNormal];
            [cell.contentView addSubview:self.gridViewButton];
            break;
        }
        default:
            break;
    }
    return cell;
} else {
    if ([self.listViewObjects count] == 0) {
        // Do something when there are no pictures or stories to show
        static NSString *CellIdentifier = @"NoPhotosYetCell";

        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

        if (cell == nil)
        {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
            cell.textLabel.textColor = [UIColor colorWithRed:0.150 green:0.143 blue:0.135 alpha:1.0];
            cell.textLabel.highlightedTextColor = [UIColor whiteColor];
            cell.selectionStyle = UITableViewCellSelectionStyleNone;
            cell.textLabel.text = @"No photos have been added yet.";
        }
        return cell;
    }
    else {
        if (self.isGridView == YES) {
            static NSString *CellIdentifier = @"EventContentGridViewCell";

            EventDetailGridRow *cell = (EventDetailGridRow *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];

            if (cell == nil)
            {
                cell = [[EventDetailGridRow alloc] initWithFrame:CGRectMake(0, 0, 306, 102)];
                cell.backgroundColor = [UIColor redColor];
            }

            NSMutableArray *mutablePhotos = [NSMutableArray arrayWithArray:self.photos];

            int offset = (indexPath.row * 3);
            int maxRange = 3;

            if (([mutablePhotos count] < (offset + maxRange)))
            {
                maxRange = ([mutablePhotos count] - offset);
            }
            NSArray *firstThree = [mutablePhotos subarrayWithRange:NSMakeRange(offset, maxRange)];

            cell.photos = firstThree;

            return cell;

        } else {
            static NSString *CellIdentifier = @"EventContentListViewCell";

            EventDetailListRowCell *cell = (EventDetailListRowCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];

            if (cell == nil)
            {
                cell = [[EventDetailListRowCell alloc] initWithFrame:CGRectMake(0, 0, 306, 400)];
            }

            NSString *authorName;
            NSString *authorUID;
            BOOL isPhoto = YES;

            if ([[self.listViewObjects objectAtIndex:indexPath.row] valueForKey:@"caption"] != nil)
            {
                // It's a photo object
                NSDictionary *photo = [self.listViewObjects objectAtIndex:indexPath.row];
                NSString *photoID = [photo valueForKey:@"id"];
                NSString *photoName = [photo valueForKey:@"image_file_name"];
                NSURL *photoURL = [NSURL URLWithString:[NSString stringWithFormat:@"http://s3.amazonaws.com/motlee-development-photos/images/%@/compressed/%@", photoID, photoName]];
                authorName = [photo valueForKeyPath:@"owner.name"][0];
                authorUID = [photo valueForKeyPath:@"owner.uid"][0];

                UIImageView *imageContainer = [[UIImageView alloc] initWithFrame:CGRectMake(0, 20, 300, 300)];
                [imageContainer setImageWithURL:photoURL];
                [cell.contentView addSubview:imageContainer];
            }
            else if ([[self.listViewObjects objectAtIndex:indexPath.row] valueForKey:@"body"] != nil)
            {
                isPhoto = NO;
                NSDictionary *story = [self.listViewObjects objectAtIndex:indexPath.row];
                authorName = [story valueForKeyPath:@"owner.name"][0];
                authorUID = [story valueForKeyPath:@"owner.uid"][0];

                UIImageView *imageContainer = [[UIImageView alloc] initWithFrame:CGRectMake(0, 20, cell.frame.size.width, 148)];
                imageContainer.image = [UIImage imageNamed:@"storyContainer"];
                [cell.contentView addSubview:imageContainer];

                UILabel *storyBody = [[UILabel alloc] initWithFrame:CGRectMake(30, 20, (306 - 60), 148)];
                storyBody.numberOfLines = 3;
                storyBody.backgroundColor = [UIColor clearColor];
                storyBody.textAlignment = NSTextAlignmentCenter;
                storyBody.font = [UIFont fontWithName:@"Helvetica" size:17];
                storyBody.textColor = [UIColor whiteColor];
                storyBody.text = [NSString stringWithFormat:@"\"%@\"", [story valueForKey:@"body"]];
                [cell.contentView addSubview:storyBody];

            }
            else {
                // Something screwy going on here, should have been one of the above objects
            }

            NSURL *profilePicURL = [NSURL URLWithString:[NSString stringWithFormat:@"http://graph.facebook.com/%@/picture", authorUID]];
            UIImageView *profilePic;
            if (isPhoto) profilePic = [[UIImageView alloc] initWithFrame:CGRectMake(20, 347, 40, 40)];
            else profilePic = [[UIImageView alloc] initWithFrame:CGRectMake(20, 179, 40, 40)];
            [profilePic setImageWithURL:profilePicURL placeholderImage:[UIImage imageNamed:@"placeholder"]];
            [cell.contentView addSubview:profilePic];

            UILabel *takenByLabel;
            if (isPhoto) {
                takenByLabel = [[UILabel alloc] initWithFrame:CGRectMake(70, 342, 170, 30)];
            }
            else {
                takenByLabel = [[UILabel alloc] initWithFrame:CGRectMake(70, 174, 170, 30)];
            }

            takenByLabel.textColor = [UIColor lightGrayColor];
            takenByLabel.font = [UIFont fontWithName:@"Helvetica" size:12];
            takenByLabel.backgroundColor = [UIColor clearColor];
            if (isPhoto) takenByLabel.text = @"taken by";
            else takenByLabel.text = @"written by";
            [cell.contentView addSubview:takenByLabel];

            UILabel *photoTakerLabel;
            if (isPhoto) {
                photoTakerLabel = [[UILabel alloc] initWithFrame:CGRectMake(70, 360, 170, 30)];
            }
            else {
                photoTakerLabel = [[UILabel alloc] initWithFrame:CGRectMake(70, 192, 170, 30)];
            }
            photoTakerLabel.textColor = [UIColor whiteColor];
            photoTakerLabel.font = [UIFont fontWithName:@"Helvetica" size:14];
            photoTakerLabel.backgroundColor = [UIColor clearColor];
            photoTakerLabel.text = authorName;
            [cell.contentView addSubview:photoTakerLabel];
            return cell;
        }
    }
}
}

The log output:

libobjc.A.dylib`objc_msgSend:
0x1f5908c:  movl   8(%esp), %ecx
0x1f59090:  movl   4(%esp), %eax
0x1f59094:  testl  %eax, %eax
0x1f59096:  je     0x1f590e8                 ; objc_msgSend + 92
0x1f59098:  movl   (%eax), %edx
0x1f5909a:  pushl  %edi
0x1f5909b:  movl   8(%edx), %edi   <-- EXC_BAD_ACCESS (code=2, address=0xb0000008)
Community
  • 1
  • 1
Scott Lieberman
  • 289
  • 2
  • 11
  • 1
    You haven't been able to get the specific line on which the crash happens, or it varies too much to be able to tell you the solution? Nowadays Apple seem to require you manually to add an exception breakpoint to catch the exact line if that's preventing that. The specific line would be a helpful clue in figuring out what's going on overall. – Tommy Nov 08 '12 at 21:46
  • That's way too much code for anyone to wade through based on your hunch about where the error is. You should add an exception breakpoint as Tommy suggested, and see if that will point you to the offending line of code. – rdelmar Nov 08 '12 at 22:38
  • @Tommy, I haven't been able to get the specific line. When I put the NSLogs into the code, it was always crashing around two different places. However, both of those places were returning a cell in the cellForRowAtIndexPath method. – Scott Lieberman Nov 09 '12 at 06:31

1 Answers1

2

Looks like you are missing cellIdentifier while initializing at some places.

static NSString *CellIdentifier = @"EventContentGridViewCell";

EventDetailGridRow *cell = (EventDetailGridRow *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
   cell = [[EventDetailGridRow alloc] initWithFrame:CGRectMake(0, 0, 306, 102)];//where is CellIdentifier?? 

It should have been something like,

cell = [[EventDetailGridRow alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.frame = CGRectMake(0, 0, 306, 102);

I am not able to see cellIdentifier "EventContentGridViewCell" set while creating the object for EventDetailGridRow. The same thing applies to all other custom cell classes in the above code. However I am not sure this alone is the issue in the above code.

If the above changes doesn't fix your issues, check this How to add a breakpoint to objc_exception_throw? and Stack trace or more info on unhandled exception in Xcode/iPhone. Should help you to figure out where the issue is happening.

Community
  • 1
  • 1
iDev
  • 23,310
  • 7
  • 60
  • 85
  • 1
    :: >>Note: It is always better to declare a variable as, UILabel *photoTakerLabel = nil; than just UILabel *photoTakerLabel;. Nothing wrong with this, but in case you miss the else part you can avoid a crash. -- untrue!? Doesnt ARC set pointers to nil on init nowadays...!? – Daij-Djan Nov 09 '12 at 01:03
  • the missing identifiers shouldnt lead to a crash IMHO... but I saw that too in one if branch (not in all cases) – Daij-Djan Nov 09 '12 at 01:04
  • Thanks for pointing it out. Before ARC came into picture, it was always recommended to set it as nil, as a good practice. Check this. stackoverflow.com/questions/9215646/…. Actually I didnt think about the ARC part while writing the answer. But still the dequereusable part is needed and otherwise I dont think it will reuse the cells next time. I have updated my answer. – iDev Nov 09 '12 at 01:15
  • you are right, before arc it was really good! It might be personal preference, but I usually omit all I can :D -- further you are right about the cells not being reused. – Daij-Djan Nov 09 '12 at 01:22
  • 1
    @ACB Thank you very much! It appears that your fix solved the issue. I still need to do a bit more testing to verify that it is indeed 100% solved, but for the time being it is no longer giving me the exc_bad_access error where I was getting it before. – Scott Lieberman Nov 09 '12 at 06:45
  • 1
    @ScottLieberman, nice to hear that. Please go through the other two links provided in the answer to see you can detect the crash. That should help. – iDev Nov 09 '12 at 06:47
  • 1
    +1 for the answer and +1 for the references. These will be very helpful not only for this particular error, but for any future errors as well. Thanks. – Scott Lieberman Nov 09 '12 at 06:57