In iOS 16.4 I have 3 view controllers. The first one has a button that will show "show eg. push" VC1 nothing more. In VC1, using UILongPressGestureRecognizer
to show VC2 over segue.
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
}
class V1: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let longPressGesture = UILongPressGestureRecognizer(
target: self,
action: #selector(cellWasPressed)
)
longPressGesture.minimumPressDuration = 1.0
view.addGestureRecognizer(longPressGesture)
}
@objc func cellWasPressed() {
performSegue(withIdentifier: "V2", sender: nil)
}
}
class V2: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
}
When I run the app and use a longpress, the following error appears:
VC1:2023-07-15 16:09:24.793114+0200 Test[58575:37092762] [SystemGestureGate] <0x15d5054e0> Gesture: System gesture gate timed out.
023-07-15 16:09:25.549590+0200 Test[58575:37092762] [Presentation] Attempt to present <Test.V2: 0x161a06fa0> on <Test.V1: 0x161a05ad0> (from <Test.V1: 0x161a05ad0>) whose view is not in the window hierarchy.
I don't want to use the navigation controller.
I searched many solutions, use topViewController()
functions, call DispatchQueue.main.async
, etc. The error is always the same.
What's wrong? I would like to solve the hierarchy problem once and for all.
It appears you are using a Modal segue to present VC2, and longPressGesture is trying to present it twice - once when the long press begins and again when it ends. Since it is a Modal segue, VC1 is no longer in the hierarchy on the second attempt to present VC2, and you get the error.
The fix is to only present VC2 when the long press begins.
@objc func cellWasPressed(sender: UILongPressGestureRecognizer) {
if sender.state == .began {
performSegue(withIdentifier: "V2", sender: nil)
}
}