10

I'm trying to add a custom delegate to a custom UITableViewCell of mine.

On this cell I have a button which need to fire a method in the ViewController where the UITableView is located on.

I'm doing all the usual steps to add a custom delegate but for some reason when I open the VC on runtime the app crashes and gives me a bad access error.

When I comment all the delegate code it works properly so my guess is that something is wrong the way I add my delegate. When I leave my id property uncommented it seems to crash.

I implement the protocol in the VC. I did assign the delegate to the cell in the cellForRowAtIndexPath:. All the delegate methods are in place. I've been using similar constructions in other classes but never in a subclass of UITableViewCells before.

Before I post some code I would like to know if someone encountered this bug before. If and how he solved it or if it is even possible to make a custom delegate for an UITableViewCell subclass.


EDIT:

My customCell.h

#import <UIKit/UIKit.h>

@class MyTableViewCell;

@protocol MyTableCellProtocoll <NSObject>

-(void) didPressButton:(MyTableViewCell *)theCell;

@end

@interface MyTableViewCell : UITableViewCell
{

    UIButton *myButton;

    id<MyTableCellProtocoll> delegationListener;

}

@property (nonatomic,retain) UIButton *myButton;

@property (nonatomic,assign) id<MyTableCellProtocoll> delegationListener;

- (void) buttonAction;

@end

.m

#import "MyTableViewCell.h"

@implementation MyTableViewCell

@synthesize myButton;
@synthesize delegationListener;

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        // Initialization code

        self.myButton = [UIButton buttonWithType:UIButtonTypeCustom];
        self.myButton.backgroundColor = [UIColor clearColor];
        self.myButton.frame = CGRectMake(5, 0, 10, 32);
        self.myButton.titleLabel.adjustsFontSizeToFitWidth = YES;
        [self.myButton addTarget:self action:@selector(buttonAction) forControlEvents:UIControlEventTouchUpInside];
        [self.contentView addSubview:self.myButton];  
    }
    return self;
}

- (void) buttonAction
{
    NSLog(@"buttonpressed");
    [self.delegationListener didPressButton:self];
}

@end

MyVC implements the delegate as proper in the .h

@interface MyVC : UIViewController <UITableViewDelegate, UITableViewDataSource, MyTableCellProtocoll>

and it also uses the one delegatemethod from MyTableCellProtocoll in the .m

- (void)didPressButton:(MyTableViewCell *)theCell
{
    NSLog(@"didPressButton");
}

I assign the delegate in the cellForRowAtIndexPath:

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

    MyTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[MyTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
        cell.delegationListener = self;
    }

    return cell;
}

These are all locations I use for the delegate. What I want it to do is change the buttontitle and insert some rows after that cell (modified duplicates)

Hope this will clear things up a bit more.


EDIT2: The button method is not being called at start as was metioned in the comment section. Editted code with logcode.


EDIT3: There is nothing wrong with the button. It is the delegate property that is messed up somewhere. With breakpoints and logs and commenting i made sure of that.

The code is being run up to the last element in my datasource list then it crashes. 1 step closer to the problem now i suppose.


FINAL EDIT: Ok, it seems like all of the delegates and buttons and other components weren't the problem at all. It was the heightForRowAtIndexPath: screwing me over. Thanks for all of your support anyhow!

Totumus Maximus
  • 7,543
  • 6
  • 45
  • 69
  • Can't comment without the code. But yes, a UITableViewCell can use a UIViewController as a delegate - your problem sounds like the standard incorrect usage of delegates. And... delegation might not be the best solution, depending. – Paul Lynch Nov 09 '11 at 09:21
  • There is no reason why it should be impossible to create a delegate protocol and id ivar in a NSObject subclass (which UITableViewCell is) – jbat100 Nov 09 '11 at 09:27
  • @PaulLynch: I edited the question with some of my code. These locations have the usage of my delegate actions. Hope it helps. – Totumus Maximus Nov 09 '11 at 09:49
  • And... where does the BAD ACCESS occur, and I suspect the buttonAction method may be being called from the init somehow. Worth putting some code in to check (an NSLog). – Paul Lynch Nov 09 '11 at 10:17
  • It appears to be the moment he wants to load a tablecell into the table. Since an empty table doesn't crash. Adding an item to it or loading with items in it makes it crash. The good old debugger doesn't provide me the exact spot of the crash -_-' Also the button is not being called, made a log into it and didn't show up. – Totumus Maximus Nov 09 '11 at 10:46
  • The code is being run up to the last element in my datasource list then it crashes. 1 step closer to the problem now i suppose. – Totumus Maximus Nov 09 '11 at 11:25
  • 1
    I think you need to put a breakpoint (possibly in cellForRowAtIndexPath) and find out exactly _where_ you are crashing, otherwise we're all going to keep throwing guesses at you :) – jrturton Nov 09 '11 at 11:27
  • @jrturton The moment it crashes after he returns the 5th (and last element) of some hardcoded datasource array. After that it steps through heighForRowAtIndexPath: and gives a load of assembly code. – Totumus Maximus Nov 09 '11 at 12:19
  • Well it appears to be the heightForRowAtIndexPath: A hardcoded value there gives me a clean load. With the delegate running normally. I changed the code there and it works now. Thanks for all of your support though! – Totumus Maximus Nov 09 '11 at 12:27
  • The only reason I up voted this Q&A thread is that I'm in search of setting up delegate protocols on `UITableViewCell` objects. Great! – Randika Vishman Jul 06 '16 at 08:32

3 Answers3

4

I have heard that synthesized accessors should not be used during init. Try to do all the setup code using the ivars directly:

myButton = [[UIButton alloc] init];         
myButton.backgroundColor = [UIColor clearColor];         
myButton.frame = CGRectMake(5, 0, 10, 32);         myButton.titleLabel.adjustsFontSizeToFitWidth = YES;         
[myButton addTarget:self action:@selector(buttonAction) forControlEvents:UIControlEventTouchUpInside];         
[contentView addSubview:myButton];

If you change your button creation to [UIButton buttonWithType:UIButtonTypeCustom]; as beryllium rightly suggests, then you will also need to retain it.

jrturton
  • 118,105
  • 32
  • 252
  • 268
  • Its not the button that is messed up here tho. When the button is commented out completely it still gives me the same bad_access error. – Totumus Maximus Nov 09 '11 at 11:15
4

This question has been solved. The problem wasn't in the delegate and unrelated to the button issues in the other answers. The problem was lying in the access of a cell in the heightForRowAtIndexpath: and was easily solved once figured out.

I was kindly pointed to the right direction by jrturton and for this he has my thanks.

Totumus Maximus
  • 7,543
  • 6
  • 45
  • 69
1

At first your interface called MyTableViewCell, implementation - iPadCheckTableViewCell. I think both should have the same name.

And create button like this:

self.myButton = [UIButton buttonWithType:UIButtonTypeCustom]; // instead of self.myButton = [[UIButton alloc] init]; - it's a memory leak
beryllium
  • 29,669
  • 15
  • 106
  • 125