我正在尝试在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];