target:self 的 UIButton 没有发送给自己?
UIButton with target:self not being sent to self?
我正在创建一个新的 UIViewController(称之为 MyViewController),并将视图 (MyView) 添加为 TableViewCell 的子视图。在 MyView 中,有一个按钮。该按钮是在 MyViewController 的初始化期间以编程方式创建的,如下所示:
-(id)initWithFrame:(CGRect)frame {
self = [super init];
if(self) {
[self.view setFrame:frame];
_yesButton = [[UIButton alloc] initWithFrame:CGRectMake(frame.size.width-150, 40, 140, 30)];
[_yesButton setTitle:@"Yeah!" forState:UIControlStateNormal];
[_yesButton addTarget:self action:@selector(didClick) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_yesButton];
}
return self;
}
现在,看起来很简单。它显示正确,模拟器中的一切看起来都很棒。
但是,当我在 MyView 中单击“_yesButton”时,出现崩溃并出现以下错误:
-[_UITableViewCellSeparatorView didClick]: unrecognized selector sent to instance 0x7b7f7ec0
什么? “_UITableViewCellSeparatorView”是什么时候出现的?我特意告诉 _yesButton 将 Target 设置为 "self",所以应该将选择器发送到 MyViewController,对吗?我什至可以想象它被绊倒并将其发送到 UITableViewCell,因为 MyView 嵌入在 TableViewCell 中,但为什么是 SeperatorView?
谁能告诉我如何让我的 _yesButton 将调用发送回在其中创建它的 MyViewController?至于加分项,你能解释一下“_UITableViewCellSeparatorView”是如何成为这次对话中的一件事的吗?
编辑: 下面是我在 TableView 中构建单元格并将 MyView 添加到其中的方法。请注意,我故意不对此行使用出列,但如果它是问题的根源,那可能会改变。
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"MyViewCell"];
MyViewController *myViewController = [[MyViewController alloc] initWithFrame:cell.contentView.frame];
[cell.contentView addSubview:myViewController.view];
return cell;
而且 didClick 方法目前是空的(它从来没有到达那里,所以我还没有写那么远),但它目前在 MyViewController 中简单地定义为:
-(void)didClick {
}
解决方案#1
其实这是因为你MyViewController
没有被ARC保留。正在调用的 dealloc
方法 ID。在您的 UITableViewController
中添加控制器的 ans 实例将解决问题并使 ARC 保留您的控制器。
解决方案#2
尝试这样的事情。
创建自定义 UITableViewCell
:
MyCustomCell.h :
#import <UIKit/UIKit.h>
@interface MyCustomCell : UITableViewCell
@property (strong, nonatomic) UIButton *yesButton;
-(id)initWithFrame:(CGRect)frame;
@end
MyCustomCell.m :
#import "MyCustomCell.h"
@implementation MyCustomCell
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
-(id)initWithFrame:(CGRect)frame {
self = [super init];
if(self) {
[self.view setFrame:frame];
_yesButton = [[UIButton alloc] initWithFrame:CGRectMake(frame)];
[_yesButton setTitle:@"Yeah!" forState:UIControlStateNormal];
[self.contentView addSubview:_yesButton];
}
return self;
}
@end
在你的UITableViewController
viewDidLoad
函数中:
[self.tableView registerClass:[MyCustomCell class] forCellReuseIdentifier:CellIdentifier];
然后在你的 tableView:cellForRowAtIndexPath:
MyCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifierr forIndexPath:indexPath];
if (cell == nil) {
cell = [[MyCustomCell alloc] initWithFrame:frame];
[cell.yesButton addTarget:self action:@selector(didClick) forControlEvents:UIControlEventTouchUpInside];
}
现在在您的 UITableViewController
中实施以下内容:
-(void)didClick {
// The following identify the in which cell the action has been triggered
NSSet *touches = [event allTouches];
UITouch *touch = [touches anyObject];
CGPoint currentTouchPosition = [touch locationInView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint: currentTouchPosition];
if (indexPath != nil)
{
// Do whatever you want for the given cell
}
}
问题是你认为 MyViewController
的实例,它不是。而是 UITableViewCellSeparatorView
.
最大的错误是,您试图通过 class UIViewController
不支持的方法初始化视图控制器,但是而是 UIView
:
的一部分
- (id)initWithFrame:(CGRect)frame
我建议您先查看一下再继续。
我认为你采用了错误的方法。
视图单元不像视图那样存在于内存中。可以说,画完了,就不存在了。
对于所有单元格操作,您应该将您的TableViewController 设置为目标,并在该控制器中处理click 方法。
只有此控制器对单元格中的数据和单元格格式具有全局知识。
您可以将按钮的标签设置为行索引,以了解点击了哪一行。
您的 didClick 选择器也不正确。它应该有这种形式
-(void)didClick:(id)sender
{
NSInteger clickedRow = ((UIButton*)sender).tag
}
所以这样连接:
[_yesButton addTarget:<YourTableController> action:@selector(didClick:) forControlEvents:UIControlEventTouchUpInside];
我正在创建一个新的 UIViewController(称之为 MyViewController),并将视图 (MyView) 添加为 TableViewCell 的子视图。在 MyView 中,有一个按钮。该按钮是在 MyViewController 的初始化期间以编程方式创建的,如下所示:
-(id)initWithFrame:(CGRect)frame {
self = [super init];
if(self) {
[self.view setFrame:frame];
_yesButton = [[UIButton alloc] initWithFrame:CGRectMake(frame.size.width-150, 40, 140, 30)];
[_yesButton setTitle:@"Yeah!" forState:UIControlStateNormal];
[_yesButton addTarget:self action:@selector(didClick) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_yesButton];
}
return self;
}
现在,看起来很简单。它显示正确,模拟器中的一切看起来都很棒。
但是,当我在 MyView 中单击“_yesButton”时,出现崩溃并出现以下错误:
-[_UITableViewCellSeparatorView didClick]: unrecognized selector sent to instance 0x7b7f7ec0
什么? “_UITableViewCellSeparatorView”是什么时候出现的?我特意告诉 _yesButton 将 Target 设置为 "self",所以应该将选择器发送到 MyViewController,对吗?我什至可以想象它被绊倒并将其发送到 UITableViewCell,因为 MyView 嵌入在 TableViewCell 中,但为什么是 SeperatorView?
谁能告诉我如何让我的 _yesButton 将调用发送回在其中创建它的 MyViewController?至于加分项,你能解释一下“_UITableViewCellSeparatorView”是如何成为这次对话中的一件事的吗?
编辑: 下面是我在 TableView 中构建单元格并将 MyView 添加到其中的方法。请注意,我故意不对此行使用出列,但如果它是问题的根源,那可能会改变。
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"MyViewCell"];
MyViewController *myViewController = [[MyViewController alloc] initWithFrame:cell.contentView.frame];
[cell.contentView addSubview:myViewController.view];
return cell;
而且 didClick 方法目前是空的(它从来没有到达那里,所以我还没有写那么远),但它目前在 MyViewController 中简单地定义为:
-(void)didClick {
}
解决方案#1
其实这是因为你MyViewController
没有被ARC保留。正在调用的 dealloc
方法 ID。在您的 UITableViewController
中添加控制器的 ans 实例将解决问题并使 ARC 保留您的控制器。
解决方案#2
尝试这样的事情。
创建自定义 UITableViewCell
:
MyCustomCell.h :
#import <UIKit/UIKit.h>
@interface MyCustomCell : UITableViewCell
@property (strong, nonatomic) UIButton *yesButton;
-(id)initWithFrame:(CGRect)frame;
@end
MyCustomCell.m :
#import "MyCustomCell.h"
@implementation MyCustomCell
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
-(id)initWithFrame:(CGRect)frame {
self = [super init];
if(self) {
[self.view setFrame:frame];
_yesButton = [[UIButton alloc] initWithFrame:CGRectMake(frame)];
[_yesButton setTitle:@"Yeah!" forState:UIControlStateNormal];
[self.contentView addSubview:_yesButton];
}
return self;
}
@end
在你的UITableViewController
viewDidLoad
函数中:
[self.tableView registerClass:[MyCustomCell class] forCellReuseIdentifier:CellIdentifier];
然后在你的 tableView:cellForRowAtIndexPath:
MyCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifierr forIndexPath:indexPath];
if (cell == nil) {
cell = [[MyCustomCell alloc] initWithFrame:frame];
[cell.yesButton addTarget:self action:@selector(didClick) forControlEvents:UIControlEventTouchUpInside];
}
现在在您的 UITableViewController
中实施以下内容:
-(void)didClick {
// The following identify the in which cell the action has been triggered
NSSet *touches = [event allTouches];
UITouch *touch = [touches anyObject];
CGPoint currentTouchPosition = [touch locationInView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint: currentTouchPosition];
if (indexPath != nil)
{
// Do whatever you want for the given cell
}
}
问题是你认为 MyViewController
的实例,它不是。而是 UITableViewCellSeparatorView
.
最大的错误是,您试图通过 class UIViewController
不支持的方法初始化视图控制器,但是而是 UIView
:
- (id)initWithFrame:(CGRect)frame
我建议您先查看一下再继续。
我认为你采用了错误的方法。
视图单元不像视图那样存在于内存中。可以说,画完了,就不存在了。
对于所有单元格操作,您应该将您的TableViewController 设置为目标,并在该控制器中处理click 方法。 只有此控制器对单元格中的数据和单元格格式具有全局知识。
您可以将按钮的标签设置为行索引,以了解点击了哪一行。
您的 didClick 选择器也不正确。它应该有这种形式
-(void)didClick:(id)sender
{
NSInteger clickedRow = ((UIButton*)sender).tag
}
所以这样连接:
[_yesButton addTarget:<YourTableController> action:@selector(didClick:) forControlEvents:UIControlEventTouchUpInside];