One of my new projects dynamically generates a UI based on a DSL entered by the user. This leads to a host of defensive coding challenges since there is multiple code paths that can add controls and their associated gesture recognizers.
I found it helpful to add guard statements that stop recognizers from being added twice. The same approach is used for controls, but that is a different topic.
The below utility function can be used to check if the provided recognizer is already in the recognizer collection associated with an object.
func containsGestureRecognizer(recognizers: [UIGestureRecognizer]?, find: UIGestureRecognizer) -> Bool { | |
if let recognizers = recognizers { | |
for gr in recognizers { | |
if gr == find { | |
return true | |
} | |
} | |
} | |
return false | |
} |
The following code shows the utility function in action. All you have to do is incorporate containsGestureRecognizer into your guard statements.
/// Example adding it the first time | |
let recognizer = UITapGestureRecognizer(target: self, action: #selector(self.handleTap(_:))) | |
view.addGestureRecognizer(recognizer) | |
/// Test if gesture already added, if added return else add the recognizer | |
guard containsGestureRecognizer(recognizers: view.gestureRecognizers, find: recognizer) == false else { return } | |
/// Add the recognizer | |
view.addGestureRecognizer(recognizer) |
Although really an edge case this was a fun bit of code to try out.