Use IBAction from UIButton inside custom cell in m

2019-02-05 04:08发布

问题:

I have created a custom cell with its own .m, .h and .xib file. In the cell, I have a UIButton that I added to the xib in IB.

I can receive the IBAction from the UIButton in this custom cell's .m, but really, I'd like to be forwarding that button press to the main view .m that is hosting the table (and so custom cell) and use an action there.

I've spent the last 4 hours attempting various ways of doing this - should I be using NSNotificationCenter? (I've tried Notifications lots but can't get it to work and not sure if i should be persevering)

回答1:

You need to use delegate in .h file of cell. Declare the delegate like this

@class MyCustomCell;
@protocol MyCustomCellDelegate
- (void) customCell:(MyCustomCell *)cell button1Pressed:(UIButton *)btn;
@end

then declare field and property

@interface MyCustomCell:UItableViewCell {
    id<MyCustomCellDelegate> delegate;
}

@property (nonatomic, assign) id<MyCustomCellDelegate> delegate;

@end

in .m file

@synthesize delegate;

and in button method

- (void) buttonPressed {
    if (delegate && [delegate respondToSelector:@selector(customCell: button1Pressed:)]) {
        [delegate customCell:self button1Pressed:button];
    }
}

Your view controller must adopt this protocol like this

.h file

#import "MyCustomCell.h"

@interface MyViewController:UIViewController <MyCustomCellDelegate>
.....
.....
@end

in .m file in cellForRow: method you need add property delegate to cell

cell.delegate = self;

and finally you implement the method from protocol

- (void) customCell:(MyCustomCell *)cell button1Pressed:(UIButton *)btn {

}

Sorry for my english, and code. Wrote it from my PC without XCODE



回答2:

I had the same problem, and I solved it by subclassing the cell into it's own class, and put the buttons there as outlets, and filling the cell with data from the model, while using a method that returns the cell we're currently viewing.

For example, if you had a Person class, and each person had a name, a surname, and a number of friends. And each time you clicked a button in the cell, the number of friends for a specific person would increase by 1.

_______________DATA SOURCE___________________________
#import <Foundation/Foundation.h>

@interface Person : NSObject

@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *comment;
@property (nonatomic) NSInteger numberOfFriends;


+(instancetype)personWithName:(NSString *)aName Surname:(NSString *)aSurname;

@end

#import "Person.h"

@implementation Person

+(instancetype)personWithName:(NSString *)aName Surname:(NSString *)aSurname{

    Person *person = [[Person alloc] init];
    [person setName:aName];
    [person setSurname:aSurname];
    [person setNumberOfFriends:0];

    return person;
}

@end

_____________________PERSON CELL________________________

#import <UIKit/UIKit.h>

@interface PersonCell : UITableViewCell

@property (strong, nonatomic) IBOutlet UILabel *friendsNum;
@property (strong, nonatomic) IBOutlet UIButton *friendsBtn;
@property (strong, nonatomic) IBOutlet UILabel *nameLabel;
@property (strong, nonatomic) IBOutlet UILabel *surnameLabel;


@end

Personally I created a private NSArray to hold the names of my Person objects, and a private NSMutableDictionary to hold my Person objects, and I set the keys to be the names of the people.

_____________________PERSON TABLE VIEW________________________    
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    PersonCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
    NSString *name = [peopleNames objectAtIndex:indexPath.row];
    Person *person = [people objectForKey:name];

    if(cell == nil)
    {
        cell = [[PersonCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }

    // Configure the cell...
    cell.nameLabel.text = person.name;
    cell.surname.Label.text = person.surname

    [cell.friendsButton addTarget:self action:@selector(moreFriends:) forControlEvents:UIControlEventTouchUpInside];

    cell.friendsNum.text = [NSString stringWithFormat:@"%i", person.numberOfFriends];

    return cell;
}

- (IBAction)moreFriends:(id)sender {
    UIButton *btn = (UIButton *)sender;
    PersonCell *cell = [self parentCellForView:btn];
    Person *person = [people objectForKey:cell.nameLabel.text];
    person.numberOfFriends++;
    [self.tableView reloadData];
}

-(PersonCell *)parentCellForView:(id)theView
{
    id viewSuperView = [theView superview];
    while (viewSuperView != nil) {
        if ([viewSuperView isKindOfClass:[PersonCell class]]) {
            return (PersonCell *)viewSuperView;
        }
        else {
            viewSuperView = [viewSuperView superview];
        }
    }
    return nil;
}


回答3:

I would recommend using a delegate.



回答4:

You might want to just add a selector for the button in your view controller which has your tableview.

in your cellForIndexPath function

[yourCell.button addTarget:self action:@selector(customActionPressed:) forControlEvents:UIControlEventTouchDown];

then handle the button press in your "customActionPressed:(id) sender" method

    //Get the superview from this button which will be our cell
UITableViewCell *owningCell = (UITableViewCell*)[sender superview];

//From the cell get its index path.
NSIndexPath *pathToCell = [myTableView indexPathForCell:owningCell];

    //Do something with our path

This may be a better solution for you unless there are more factors that you haven't listed.

I have a tutorial which is might explain more http://www.roostersoftstudios.com/2011/05/01/iphone-custom-button-within-a-uitableviewcell/



回答5:

Why not create a delegate (using @protocol) for your custom cell. You can then designate the main view as each cell's delegate and process the action appropriately.