13

我试图在 a 的子视图中触发事件UITableViewCell,并让它在响应者链中冒泡并由自定义UITableViewCell子类处理。

基本上:

SomeView.m(这是 的子视图UITableViewCell

[self.button addTarget:nil action:@selector(someAction:) events:UIControlEventTouchUpInside]

SomeCustomCell.m

- (void)someAction:(id)sender {
     NSLog(@"cool, the event bubbled up to the cell");
}

为了测试为什么这不起作用,我someAction:在 ViewController 上添加了方法,而 ViewController 是最终处理从表格视图单元子视图冒泡的事件的方法,即使 Cell 应该处理它。someAction:我已经检查了 Cell 是否在响应者链上,并且我已经验证了响应者链上的任何视图,无论是在单元上方还是下方,如果它们实现了该方法,它们都会响应事件。

这到底是怎么回事?

这是一个显示它的项目https://github.com/keithnorm/ResponderChainTest这是某种预期的行为吗?我没有找到任何说明 UITableViewCell 的处理方式与其他 UIResponder 不同的文档。

4

5 回答 5

10

该单元格似乎向其表格视图请求许可。要改变它,你当然可以覆盖

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
    return [self respondsToSelector:action];
}

斯威夫特 3、4、5:

override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
    return self.responds(to: action)
}
于 2014-06-21T17:17:00.130 回答
1

我得出的结论是,这要么是错误,要么是未记录的预期行为。无论如何,我最终通过在子视图中响应事件然后手动将消息传播到响应者链上来暴力修复它。就像是:

- (void)customEventFired:(id)sender {
  UIResponder *nextResponder = self.nextResponder;
  while (nextResponder) {
    if ([nextResponder respondsToSelector:@selector(customEventFired:)]) {
      [nextResponder performSelector:@selector(customEventFired:) withObject:sender];
      break;
    }
    nextResponder = nextResponder.nextResponder;
  }
}

我还更新了我的演示项目,以展示我如何使用这个“修复” https://github.com/keithnorm/ResponderChainTest

如果其他人解决了这个问题,我仍然欢迎任何其他想法,但这是我目前最好的。

于 2014-01-24T22:03:57.347 回答
0

这样做

    @implementation ContentView

   // uncomment this to see event caught by the cell's subview

  - (id)initWithFrame:(CGRect)frame
 {
     self = [super initWithFrame:frame];
    if(self)
   {

    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
    [button setTitle:@"Click" forState:UIControlStateNormal];
    [button setBackgroundColor:[UIColor blueColor]];
    [button addTarget:self action:@selector(customEventFired:) forControlEvents:UIControlEventTouchUpInside];
    button.frame = CGRectMake(4, 5, 100, 44);
    [self addSubview:button];
  }

    return self;
}

 - (void)customEventFired:(id)sender
{
     UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Event Triggered in cell subview" message:@"so far so good..." delegate:nil cancelButtonTitle:@"cancel" otherButtonTitles:nil, nil];
    [alertView show];
 }

@end

现在 customEventFired:方法被调用

于 2014-01-24T07:58:29.013 回答
0

您可以将 View.m 中的代码更改为

      [button addTarget:nil action:@selector(customEventFired:) forControlEvents:(1 << 24)];

      [button addTarget:cell action:@selector(customEventFired:) forControlEvents:(1 << 24)];
于 2014-01-24T08:41:56.867 回答
-1

我认为这是最简单的解决方案。如果您不指定目标,则事件将自动在响应者链中冒泡。

[[UIApplication sharedApplication]sendAction:@selector(customAction:) to:nil from:self forEvent:UIEventTypeTouches];
于 2015-06-03T13:43:31.360 回答