我如何添加一个触摸事件到一个UIView? 我试一试:

UIView *headerView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.bounds.size.width, nextY)] autorelease];
[headerView addTarget:self action:@selector(myEvent:) forControlEvents:UIControlEventTouchDown];
// ERROR MESSAGE: UIView may not respond to '-addTarget:action:forControlEvents:'

我不想创建一个子类然后重写

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

当前回答

简单实用的扩展:

extension UIView {
private struct OnClickHolder {
    static var _closure:()->() = {}
}

private var onClickClosure: () -> () {
    get { return OnClickHolder._closure }
    set { OnClickHolder._closure = newValue }
}

func onTap(closure: @escaping ()->()) {
    self.onClickClosure = closure
    
    isUserInteractionEnabled = true
    let tap = UITapGestureRecognizer(target: self, action: #selector(onClickAction))
    addGestureRecognizer(tap)
}

@objc private func onClickAction() {
    onClickClosure()
}

}

用法:

    override func viewDidLoad() {
    super.viewDidLoad()
    let view = UIView(frame: .init(x: 0, y: 0, width: 80, height: 50))
    view.backgroundColor  = .red
    view.onTap {
        print("View Tapped")
    }
}

其他回答

斯威夫特5.3

基于闭包的UIGestureRecognizer解决方案

final class BindableGestureRecognizer: UITapGestureRecognizer {
    private var action: () -> Void

    init(action: @escaping () -> Void) {
        self.action = action
        super.init(target: nil, action: nil)
        self.addTarget(self, action: #selector(execute))
    }

    @objc private func execute() {
        action()
    }
}

public extension UIView {
    /// A discrete gesture recognizer that interprets single or multiple taps.
    /// - Parameters:
    ///   - tapNumber: The number of taps necessary for gesture recognition.
    ///   - closure: A selector that identifies the method implemented by the target to handle the gesture recognized by the receiver. The action selector must conform to the signature described in the class overview. NULL is not a valid value.
    func addTapGesture(tapNumber: Int = 1, _ closure: (() -> Void)?) {
        guard let closure = closure else { return }

        let tap = BindableGestureRecognizer(action: closure)
        tap.numberOfTapsRequired = tapNumber
        addGestureRecognizer(tap)

        isUserInteractionEnabled = true
    }
}

使用:

view.addTapGesture { [weak self] in
    self?.view.backgroundColor = .red
}

在iOS 3.2及更高版本中,你可以使用手势识别器。例如,这是你处理点击事件的方式:

//The setup code (in viewDidLoad in your view controller)
UITapGestureRecognizer *singleFingerTap = 
  [[UITapGestureRecognizer alloc] initWithTarget:self 
                                          action:@selector(handleSingleTap:)];
[self.view addGestureRecognizer:singleFingerTap];

//The event handling method
- (void)handleSingleTap:(UITapGestureRecognizer *)recognizer
{
  CGPoint location = [recognizer locationInView:[recognizer.view superview]];

  //Do stuff here...
}

还有一些内置的手势。查看iOS事件处理和UIGestureRecognizer的文档。我还在github上有一堆示例代码,可能会有所帮助。

你们为什么不试试ssevenlistener呢?

您不需要创建任何手势识别器,并将您的逻辑分离到另一个方法。ssevenlistener支持在视图上设置侦听器块,以侦听单个点击手势,双击手势和N-tap手势,如果你喜欢,和长按手势。设置一个点击手势监听器是这样的:

[view ss_addTapViewEventListener:^(UITapGestureRecognizer *recognizer){…} numberOfTapsRequired: 1);

另一种方法是向视图添加一个透明按钮

UIButton *b = [UIButton buttonWithType:UIButtonTypeCustom];
b.frame = CGRectMake(0, 0, headerView.width, headerView.height);
[headerView addSubview:b];
[b addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchDown];

然后,handle click:

- (void)buttonClicked:(id)sender
{}

创建一个手势识别器(子类),它将实现触摸事件,如touchesBegan。之后可以将其添加到视图中。

这样您将使用组合而不是子类化(这是请求)。