iosswifttouches

How to prevent that an accidental touch triggering the touchesBegan in swift 4.2?


I have an App that uses touchesBegan to perform an action for the user. However, sometimes touching the screen is only to leave a textField.

Is there any way to set the touchesBeagan to only start after 2 or 3 seconds while keeping the touch and if the touch is smaller than this, instead of triggering the action, the resignFirstResponder is triggered?

To help to understanding here are my touches methods:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    Feedback.share.hapticFeedback()
    startPoint = nil
    guard let touch = touches.first else {return}
    startPoint = touch.location(in: imageView)

    //Initialize whatever you need to begin showing selected rectangle below.
    rectShapeLayer.path = nil
    imageView.layer.addSublayer(rectShapeLayer)
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard let touch = touches.first, let startPoint = startPoint else {return}
    let currentPoint: CGPoint
    if let predicted = event?.predictedTouches(for: touch), let lastPoint = predicted.last {
        currentPoint = lastPoint.location(in: imageView)
    } else {
        currentPoint = touch.location(in: imageView)
    }
    let frame = rect(from: startPoint, to: currentPoint)

    //Show bounding box
    rectShapeLayer.path = UIBezierPath(rect: frame).cgPath
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard let touch = touches.first, let startPoint = startPoint else {return}
    let currentPoint = touch.location(in: imageView)
    let frame = rect(from: startPoint, to: currentPoint)

    //Remove bounding box but take snapshot of selected `CGRect` by frame
    rectShapeLayer.removeFromSuperlayer()
    let memeImage = imageView.snapshot(rect: frame, afterScreenUpdates: true)

    save(imageView: imageView, image: memeImage)

}

Solution

  • I found out a way to guarantee that a touch on the screen it just execute a resignFirstResponder instead of other function.

    I only changed the touchesEnded(_:) method adding an "if frame.size.width < 1".

    That worked well for me.

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        guard let touch = touches.first, let startPoint = startPoint else {return}
        let currentPoint = touch.location(in: ivPhoto)
        let frame = rect(from: startPoint, to: currentPoint)
    
        rectShapeLayer.removeFromSuperlayer()
    
        if frame.size.width < 1 {
            tfTop.resignFirstResponder()
            tfBottom.resignFirstResponder()
        } else {
    
            let memeImage = ivPhoto.snapshot(rect: frame, afterScreenUpdates: true)
    
            saveCrop(cropImage: memeImage)
        }
    }