UITableViewCell上的UIButton被链接到错误的操作

时间:2014-02-26 20:56:15

标签: ios objective-c uitableview uibutton

我已经以编程方式创建了一个UITableView,并且我还以编程方式创建了UIButtons以包含在每个单元格/行中。我已经设置了这些按钮,如果它们被点击,它们的按钮图像就会改变。因此,当用户第一次看到表格视图时,按钮颜色为灰色,但如果用户点击其中一个按钮,则该按钮将变为红色。如果他们再次点击它,它将变回灰色。

我也这样做了,如果按下了一个按钮,并且当前正在使用红色图像,那么它会将它的单元格的detailTextLabel属性值传递给NSMutableArray对象。

这是问题所在。出于某种原因,除了第一个按钮之外,所有按钮都能正常工作。我的UITableView有2个部分。如果我按下第一部分中第一个单元格的按钮,由于某种原因它会抓取第二部分第一个单元格的detailTextLabel属性。

这是我的代码,它控制着大多数UITableView。这是设置单元格的textLabels和detalTextLabel的位置。它是if语句的原因是因为如果我们在数据库中找到那个人然后我们执行第一个代码,否则它们在我们的数据库中找不到,我们执行第二组代码:

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

static NSString *cellIdentifier = @"SettingsCell";

_cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

NSString* userName = nil;

if (indexPath.section == 0) {

userName = [self.potentiaFriendsInParseFirstNamesArray objectAtIndex:indexPath.row];

NSString *firstNameForTableView = [self.potentiaFriendsInParseFirstNamesArray objectAtIndex:indexPath.row];

NSString *userNameForTableView = [self.potentiaFriendsUsernameArray objectAtIndex:indexPath.row];


UIImage *addUserButtonImage = [UIImage imageNamed:@"SliderThumb-Normal-G"];
UIImage *addUserButtonImageHighlighted = [UIImage imageNamed:@"SliderThumb-Normal"];


_addUserButton.frame = CGRectMake(237, -10, 64, 64);

[_addUserButton setImage:addUserButtonImage forState:UIControlStateNormal];
[_addUserButton setImage:addUserButtonImageHighlighted forState:UIControlStateHighlighted];
[_addUserButton setImage:addUserButtonImageHighlighted forState:UIControlStateSelected];

[_addUserButton addTarget:self action:@selector(handleTouchUpInside:) forControlEvents:UIControlEventTouchUpInside];


_addUserButton.tag = indexPath.row;


[_cell.textLabel setText:firstNameForTableView];

[_cell.detailTextLabel setText:userNameForTableView];

[_cell.contentView addSubview:_addUserButton];


} else {

userName = [self.potentiaFriendsNotInParseFirstNamesArray objectAtIndex:indexPath.row];

NSString *firstNameForTableView = [self.potentiaFriendsNotInParseFirstNamesArray objectAtIndex:indexPath.row];

NSString *userNameForTableView = [self.potentiaFriendsPhoneNumberArray objectAtIndex:indexPath.row];


UIImage *addFriendButtonImage = [UIImage imageNamed:@"SliderThumb-Normal-G"];
UIImage *addFriendButtonImageHighlighted = [UIImage imageNamed:@"SliderThumb-Normal"];

UIButton *addFriendButton = [[UIButton alloc]init];

addFriendButton.frame = CGRectMake(237, -10, 64, 64);


[addFriendButton setImage:addFriendButtonImage forState:UIControlStateNormal];
[addFriendButton setImage:addFriendButtonImageHighlighted forState:UIControlStateHighlighted];     

[addFriendButton setImage:addFriendButtonImageHighlighted forState:UIControlStateSelected];

[addFriendButton addTarget:self action:@selector(handleTouchUpInsideForNonUsers:) forControlEvents:UIControlEventTouchUpInside];


addFriendButton.tag = indexPath.row;


[_cell.textLabel setText:firstNameForTableView];

[_cell.detailTextLabel setText:userNameForTableView];

[_cell.contentView addSubview:addFriendButton];

}
return _cell;
}

以下语句是方法调用,一个用于if语句的第一部分,另一个用于if语句的“else”部分。它们处理“触摸”事件,并在按下按钮时使按钮从灰色图像变为红色图像:

[_addUserButton addTarget:self action:@selector(handleTouchUpInside:) forControlEvents:UIControlEventTouchUpInside];

[addFriendButton addTarget:self action:@selector(handleTouchUpInsideForNonUsers:) forControlEvents:UIControlEventTouchUpInside];

以下是这些方法调用的方法实现。它们几乎相同,除了“handleTouchUpInside”和“handleTouchUpInsideForNonUsers”的名称,然后第一个部分设置为“0”,第二个部分设置为“1”。

- (void)handleTouchUpInside:(UIButton *)sender {
sender.selected = !sender.selected;

UIButton *cellButton = (UIButton *)sender;

NSIndexPath *indexPath = [NSIndexPath indexPathForRow:cellButton.tag inSection:0];

_cell = [_tableView cellForRowAtIndexPath:indexPath];

_cell.detailTextLabel.text = [_cell.detailTextLabel.text stringByReplacingOccurrencesOfString:@"    " withString:@""];

if(sender.state == 5) {

[_usersToAddToFriendsList addObject:_cell.detailTextLabel.text];

} else {

[_usersToAddToFriendsList removeObject:_cell.detailTextLabel.text];


}
}


- (void)handleTouchUpInsideForNonUsers:(UIButton *)sender {
sender.selected = !sender.selected;

UIButton *cellButton = (UIButton *)sender;

NSIndexPath *indexPath = [NSIndexPath indexPathForRow:cellButton.tag inSection:1];


_cell = [_tableView cellForRowAtIndexPath:indexPath];

if(sender.state == 5) {

[_usersToInviteToApp addObject:_cell.detailTextLabel.text];


} else {

[_usersToInviteToApp removeObject:_cell.detailTextLabel.text];

}   
}

我向您展示的第一个代码的另一个重要部分是我如何在if语句的两个部分设置UIButton标记。我觉得这些可能是问题的一部分:

addUserButton.tag = indexPath.row;addFriendButton.tag = indexPath.row;

这些用于为每个按钮添加标签。我添加了这些是因为我昨天在第一次尝试设置所有这些时问了一个问题,按钮标签是某人给我的解决方案的一部分。以下是我最终使用的解决方案/答案:https://stackoverflow.com/a/22030199/3344977

最后但同样重要的是,这里有最后3个方法实现,它们有助于创建我的UITableView及其所有方面:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 2 ;
}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

if(section == 0)
    return [self.potentiaFriendsInParseFirstNamesArray count];
if(section == 1)
    return [self.potentiaFriendsNotInParseFirstNamesArray count];

else return 0;
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {

if(section == 0)
    return @"Friends Using This App";
if(section == 1)
    return @"Send to Contact";

else return @"nil";
}

更新:我为单元格按钮的标签添加了一个NSLog,用于“handleTouchUpInside”和“handleTouchUpInsideForNonUsers”的方法实现。所有按钮都将正确的按钮标签打印到控制台。因此,对于第一部分中的第一个按钮,它会打印正确的按钮标签号“0”。所以我认为真正的问题是,由于某种原因,第一部分中的第一个按钮被分配到错误的部分。

我认为它被分配到第二部分而不是第一部分。

更新2:现在,当您按下其中一个按钮时,它应该访问属性“detailTextLabel.text”。除了第一部分中的第一个按钮外,所有按钮都可以正常工作。

但是对于第一个按钮,即使我将属性更改为“textLabel.text”,它仍然总是打印第二部分第一个单元格的“detailTextLabel.text”。

更新3:对于if语句的第一部分,它创建了表视图的第一部分,而不是同时为图像使用“SliderThumb-Normal”和“SliderThumb-Normal-G”,我将它们都更改为只是“SliderThumb-Normal”。果然,第一部分中的第二个单元格是正确的,并使用“SliderThumb-Normal”图像,但第一部分中的第一个单元格使用的是“SliderThumb-Normal-G”图像。

我认为当if语句运行时,第一个单元格的部分不能为“0”,因为它是通过if代码的“else”部分运行的。我只是无法弄清楚原因。

编辑TIMOTHY:我把很多内容放在主文件的界面区域和头文件中。

这是我的头文件:

@interface AddFriendsViewController : UIViewController <UITableViewDataSource>

@property (nonatomic, strong) NSMutableArray *friendsOnApp;
@property (nonatomic, retain) NSArray *objects;
@property (nonatomic, retain) NSArray *objectsFinal;
@property (nonatomic, retain) UITableView *addFriendsTableView;
@property (nonatomic, retain) PotentialFriend *potentialFriend;
@property (nonatomic, retain) PotentialFriend *potentialFriendForTableView;
@property (nonatomic, retain) NSString *potentialFriendz;
@property (nonatomic, strong) NSString *imageFile;

@property (nonatomic, strong) UITableViewCell *cell;
@property (nonatomic, strong) UITableViewCell *cellz;


@property (nonatomic, strong) UIButton *addUserButton;
@property (nonatomic, strong) UIButton *addFriendButton;


@end

这是我的主文件的界面区域:

@interface AddFriendsViewController ()

@property (nonatomic, strong) NSMutableArray* contactList;
@property (weak, nonatomic) IBOutlet UITableView *tableView;

@property (strong, nonatomic) NSMutableArray *potentiaFriendsInParseFirstNamesArray;
@property (strong, nonatomic) NSMutableArray *potentiaFriendsUsernameArray;

@property (strong, nonatomic) NSMutableArray *potentiaFriendsNotInParseFirstNamesArray;
@property (strong, nonatomic) NSMutableArray *potentiaFriendsPhoneNumberArray;

@property (strong, nonatomic) NSMutableArray *removalPhoneNumberArray;


@property (strong, nonatomic) NSMutableArray *usersToAddToFriendsList;
@property (strong, nonatomic) NSMutableArray *usersToInviteToApp;

@end

然后我在主文件的viewDidLoad方法实现中初始化它们:

- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.

//This sets the UITableView's data source as itself.

self.tableView.dataSource = self;

self.potentiaFriendsInParseFirstNamesArray = [[NSMutableArray alloc] init];
self.potentiaFriendsUsernameArray = [[NSMutableArray alloc]init];

self.potentiaFriendsNotInParseFirstNamesArray = [[NSMutableArray alloc]init];
self.potentiaFriendsPhoneNumberArray = [[NSMutableArray alloc]init];

self.removalPhoneNumberArray = [[NSMutableArray alloc]init];


self.usersToAddToFriendsList = [[NSMutableArray alloc]init];
self.usersToInviteToApp = [[NSMutableArray alloc]init];

self.addUserButton = [[UIButton alloc]init];
self.addFriendButton = [[UIButton alloc]init];


self.cell = [[UITableViewCell alloc]init];

3 个答案:

答案 0 :(得分:0)

我创建了一个示例项目,将每个单元格中的按钮背景变为灰色,并在点击时将其变回白色。看看我的代码,以便您可以相应地修改代码。

我创建了两个类。第一个是UITableViewController,第二个是UITableViewCell。

如果您感到困惑并且无法将其集成到您的项目中,我建议您单独运行它。然后,您可以逐个复制并粘贴代码,直到达到您想要的程度。祝你好运!

<强> TableViewController.h

#import <UIKit/UIKit.h>

@interface TableViewController : UITableViewController

@end

<强> TableViewController.m

#import "TableViewController.h"
#import "CustomCell.h"

@interface TableViewController ()

@property NSArray *tableDataArray;

@end

@implementation TableViewController

- (id)initWithStyle:(UITableViewStyle)style {
self = [super initWithStyle:style];
if (self) {
    // Custom initialization
    }
return self;
}

- (void)viewDidLoad {
[super viewDidLoad];

self.tableDataArray = [[NSArray alloc] initWithObjects:@"First line", @"Second line", @"Third line", @"Fourth line", @"Fifth line", nil];
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}

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

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
    cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }
cell.IndexPath = indexPath;

return cell;
}

@end

<强> CustomCell.h

#import <UIKit/UIKit.h>

@interface CustomCell : UITableViewCell

@property (nonatomic, strong) NSIndexPath *indexPath;
@property (nonatomic, strong) UIButton *theButton;

-(void)didTapButtonInCell;

@end

<强> CustomCell.m

#import "CustomCell.h"

@implementation CustomCell

@synthesize indexPath, theButton;

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
    // Initialization code
    theButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    theButton.backgroundColor = [UIColor whiteColor];
    [theButton setFrame:CGRectMake(0, 0, 75, 30)];
    [theButton addTarget:self action:@selector(didTapButtonInCell) forControlEvents:UIControlEventTouchUpInside];
    self.accessoryView = theButton;
    }
return self;
}

-(void)setIndexPath:(NSIndexPath *)theIndexPath {
indexPath = theIndexPath;
UILabel *theLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 7, 200, 25)];
[theLabel setFont:[UIFont systemFontOfSize:18]];
[theLabel setText:[NSString stringWithFormat:@"Row %d", self.indexPath.row]];
[self.contentView setBackgroundColor:[UIColor clearColor]];
[self.contentView addSubview:theLabel];
theButton = (UIButton *)self.accessoryView;
[theButton setTitle:@"Hit me!" forState:UIControlStateNormal];
theButton.backgroundColor = [UIColor whiteColor];
}

-(void)didTapButtonInCell {
NSString *messageString = [NSString stringWithFormat:@"Button at section %d row %d was tapped.", indexPath.section, indexPath.row];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Button tapped!"
                                                message:messageString
                                               delegate:nil
                                      cancelButtonTitle:@"OK"
                                      otherButtonTitles: nil];
[alert show];

if([theButton.backgroundColor isEqual:[UIColor whiteColor]])
{
    [theButton setBackgroundColor:[UIColor lightGrayColor]];
} else
    {
    [theButton setBackgroundColor:[UIColor whiteColor]];
    }
}

@end

答案 1 :(得分:0)

如果你们好奇,引起问题的原因是使用全局变量_addUserButton

我最后删除了它的属性,只是在cellForRowAtIndexPath的方法实现中初始化它。

有人可以向我解释为什么将它用作全局变量导致了这个问题吗?

答案 2 :(得分:0)

动态添加到单元格的任何元素必须由唯一标记标识,如果不存在任何元素,则只应创建它。这里按钮每次都会创建,但不应该创建。

按钮的标签应该是常量而不是像indexpath.row那样的变量。

-(UITableViewCell*)tableview:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
   if([cell.contentView viewWithTag:10])
   {
      UIButton *btn=[UIButton buttonWithType:UIButtonTypeDetailDisclosure];
      btn.tag=10;
      [cell.contentView addSubView:btn];
   }
   UIButton *button=[cell.contentView viewWithTag:10])
   //do button customizations
}

现在在触摸事件中唯一标识按钮的单元格和索引路径

- (void)handleTouchUpInside:(UIButton *)sender
{
    UITableViewCell *cell=(UITableViewCell*)sender.superview.superview.superview;
    NSIndexPath *indexPath=[self.tableView indexPathForCell:cell];
    //do action based on indexpath
}