在 UIView 代码中创建的 UIGestureRecognizer 不起作用

UIGestureRecognizer created in UIView code not working

我有一个 UIStackView 的自定义子 class,里面有一些 UIImageViews。我希望视图接受平移手势来跟踪在其表面上的缓慢滑动。当我在 Interface Builder 中配置 UIPanGestureRecognizer 时,它可以工作,但在代码中没有。这是 class 的缩写版本:

@IBDesignable
class CustomView: UIStackView {

    private let panRecognizer = UIPanGestureRecognizer(target: self, action: #selector(CustomView.singleFingerSwipe))


    override init(frame: CGRect) {
        super.init(frame: frame)

        initializeProperties()
    }

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)

        initializeProperties()
    }

    @IBAction
    private func singleFingerSwipe(_ sender: UIPanGestureRecognizer) {
        print("Panning...")
    }

    private func initializeProperties() {
        addGestureRecognizer(panRecognizer)

        for _ in 1...3 {
            let imageView = UIImageView(image: UIImage(named: "MyImage"))
            imageView.translatesAutoresizingMaskIntoConstraints = false
            imageView.isUserInteractionEnabled = true

            addArrangedSubview(imageView)
            imageView.widthAnchor.constraint(equalTo: imageView.heightAnchor).isActive = true
            imageView.heightAnchor.constraint(equalTo: self.heightAnchor).isActive = true
        }
    }
}

当我在星形视图内滑动时,没有打印输出。但是,如果我将 Pan Gesture Recognizer 放到 IB 中的视图上并将其连接到同一个选择器,它就可以正常工作。我错过了什么?

使您的 panRecognizer 惰性 var 使其初始化延迟到第一次使用和设置堆栈视图的框架时。喜欢

    private lazy var panRecognizer = UIPanGestureRecognizer(target: self, action: #selector(CustomView.singleFingerSwipe))

或 将 panRecognizer 的声明移动到 addGesture 调用之前的 initializeProperties() 方法。喜欢

let panRecognizer = UIPanGestureRecognizer(target: self, action: #selector(CustomView.singleFingerSwipe))
addGestureRecognizer(panRecognizer)

编辑

原因是目标设置为 null,因此当您使用 "private let .." 初始化时它无法触发该方法。由于稍后会调用 init,并且不会为 CustomView 初始化对象。这是用 let(constant):

声明时的控制台日志

self.panRecognizer的打印说明: ;目标= <(action=singleFingerSwipe:, target=<(null) 0x0>)>>

但是当它的lazy var or declared in the method after init被调用时,CustomeView的实例被生成直到使用panRecognizer。控制台打印是:

self.panRecognizer.storage.some 的打印说明: ;目标= <(action=singleFingerSwipe:, target=)>>

在这里您可以看到目标已设置。

P.S。你可以用 debugger

检查一下