在UIView代码中创建的UIGestureRecognizer无法正常工作

时间:2018-01-16 00:59:17

标签: ios uiview interface-builder uigesturerecognizer uipangesturerecognizer

我有一个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中的视图上并将它连接到同一个选择器上,它就可以正常工作。我错过了什么?

1 个答案:

答案 0 :(得分:3)

使你的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 =<(action = singleFingerSwipe:,target =<(null)0x0>)>>

但是当调用它的lazy var或在init之后的方法中声明时,生成CustomeView的实例直到使用panRecognizer时。控制台打印是:

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

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

P.S。您可以使用调试器检查相同的内容