UitaiteViewCell跳过响应器链



我正在尝试在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");
}

为了测试为什么这不起作用,我在ViewController上添加了someAction:方法,并且ViewController是最终处理事件从表查看单元格子视图中弹出的事件的方法,即使该单元格处理它。我已经检查了该单元格在响应器链上,并且已经验证了响应链上和下方的任何视图,如果它们实现了someAction:方法。

这里到底发生了什么?

这是一个向其显示https://github.com/keithnorm/responderchaintest的项目吗?我没有发现任何文档说明UitableViewCell的对待与其他Uiresponder的对待不同。

单元格似乎向其表视图征求了许可。要改变您当然可以覆盖的

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

Swift 3,4,5:

override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
    return self.responds(to: action)
}

我得出的结论是,这是一个错误或无证行为。无论如何,我最终通过在子视图中响应事件,然后手动向响应器链上的消息传播,从而将其修复。类似:

- (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。

,如果其他人弄清楚这一点,我仍然欢迎其他任何想法,但这是我现在最好的。

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

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

to

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

确实喜欢这个

    @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:方法被称为

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

[[UIApplication sharedApplication]sendAction:@selector(customAction:) to:nil from:self forEvent:UIEventTypeTouches];

相关内容

  • 没有找到相关文章

最新更新