删除UIButton的目标动作

问题描述:

我有一个UIButton被添加到每个UITableViewCell(除了2个单元格)在tableview中。 该按钮的目标是UITableViewController。 我注意到,当该动作发送到错误的目标时,该应用程序崩溃。我假设这是因为目标已被解除分配(即使如果UITableViewController已被释放,按钮不应该是可见的,并且不可按(应该自行释放))。删除UIButton的目标动作

我猜我需要平衡addTarget方法,removeTarget。像KVO一样保留/发布。

但我不确定在哪里做这件事,因为我在创建并添加到单元格时只有一个引用按钮,在cellForRowAtIndexPath:

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

    static NSString *CellIdentifier = @"Cell"; 

    UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
    if (cell == nil) { 
     cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease]; 
     UIButton *extraButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 
     [extraButton setFrame:CGRectMake(0, 0, 60, 30)]; 
     [extraButton setTitle:@"Meta" forState:UIControlStateNormal]; 
     [extraButton addTarget:self action:@selector(extraButtonPressed:) forControlEvents:UIControlEventTouchUpInside]; 
     cell.accessoryView = extraButton; 
    } 

    if (indexPath.row == kNoExtraButtonRow) { 
     cell.accessoryView.hidden = YES; 
    } else { 
     cell.accessoryView.hidden = NO; 
    } 
    //set textlabels etc... 
    return cell; 
} 

如果你已经子类UIButton的这个或有子类的UITableViewCell,那么你可以将代码放在那里当电池或按钮被释放删除目标行动的按钮。在UITableViewCell的dealloc中,您可以在其按钮上调用removeTarget,或者在按钮的dealloc中调用removeTarget。

这是非常不寻常的需要做到这一点。更可能的是,你错误地用其他方式管理内存。特别是,UIButton的目标通常应该是拥有该按钮的UIViewController。在大多数优秀的设计中,按钮的寿命总是比控制器的寿命短。你在其他地方保留UIButton吗?你是否使用nib文件来管理你的按钮,或以编程方式生成它?当人们以编程方式创建它们时,意外地创建UI元素的多个实例(这是nib文件首选的几个原因之一),这种情况有点常见。

你确定使用所有的ivars访问器(特别是在这种情况下的按钮)?直接访问ivars是开发人员创建重复UI元素的最常见方式。始终使用访问器(init和dealloc除外)。

+0

孔中的细胞,只是没有UITableViewCell的一个子类。按钮[应该]寿命较短,当我得到错误时我很困惑。我没有使用笔尖。我不确定你的意思是不小心创建了多个UI元素实例?我必须创建多个实例,因为有多个单元。我会将代码添加到我的问题中。 –

+0

您的上述代码看起来正确。您可能想要发布实际的崩溃信息。 –

+0

以及堆栈跟踪相当无用,因为它在'main'方法中停止。异常是:' - [_UIResizableImage extraButtonPressed:]:无法识别的选择器发送到实例0x29c480'。这是在包含按钮的桌面视图之后,已经离开了屏幕(所以不可能触摸按钮) –

试试这个。

 if (cell == nil){ 

    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier]retain]; 
    UIButton *extraButton = [[UIButton buttonWithType:UIButtonTypeRoundedRect]retain]; 
    [extraButton setFrame:CGRectMake(0, 0, 60, 30)]; 
    [extraButton setTitle:@"Meta" forState:UIControlStateNormal]; 
    [extraButton addTarget:self action:@selector(extraButtonPressed:) forControlEvents:UIControlEventTouchUpInside]; 
    cell.accessoryView = extraButton; 
} 

删除自动释放并添加保留Tableviewcell分配和布顿分配.....

+0

但是这会造成泄漏,其中很多。 –

+0

好的...我想在你的extraButtonPressed:方法中,你检查发件人按钮(id)。只需做一件事,将标签设为按钮并在方法中检查带有按钮ID的标签。我想那样你得到了你无法识别的选择器错误..... –

你不需要removeTarget并请确保您正在设置目标自我。你的代码适合我。

假设表视图单元格进入重用队列并且未改变,但作为完整性检查,也许你想要做的是在(cell != nil)脱离出队列的情况下,想要removeTarget无论如何,重新建立目标。

基本上在(cell != nil)的情况下做你自己的内联-prepareForReuse并在每种情况下设置整个事物(除了实际的表单元格alloc)。

+0

对不起,我不太明白。我应该在if语句之外移动按钮代码?如果我这样做,那么我会在每个单元格上获得多个按钮。 –

[extraButton addTarget:nil action:@selector(extraButtonPressed:) forControlEvents:UIControlEventTouchUpInside]; 
+0

我知道如何去除它,我需要知道把这条线放在哪里。 –

我认为这将有助于

[someControl removeTarget:nil 
       action:NULL 
    forControlEvents:UIControlEventAllEvents];