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

@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设置为lazy var,以便将其初始化延迟到首次使用和设置堆栈视图的框架为止。喜欢

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

要么
在addGesture调用之前,将panRecognizer的声明移动到initializeProperties()方法。喜欢
let panRecognizer = UIPanGestureRecognizer(target: self, action: #selector(CustomView.singleFingerSwipe))
addGestureRecognizer(panRecognizer)

编辑

原因是目标正在设置为null,因此当您使用“private let ..”进行初始化时,它无法激发该方法。由于稍后会调用init,因此不会为CustomView初始化对象。这是用let(constant)声明时的控制台日志:

self.panRecognizer的打印说明:
; target = )>>

但是,当其惰性变量或在init之后的方法中声明时,将生成CustomeView的实例,直到使用panRecognizer为止。控制台打印为:

self.panRecognizer.storage.some的打印说明:
; target = >

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

附言您可以使用调试器进行检查

10-08 12:27