0

I have a UITextView object that displays an error message. The object drops down from the top of the screen like a notification. By default it stays stationary for 5 seconds and then goes back up above the view before it is then removed from the superview. I have added a UISwipeGestureRecognizer to the view however when testing, the function attached is not being called. Can anyone see what is wrong?

class ErrorMessage : UITextView {

override init(frame: CGRect, textContainer: NSTextContainer?) {
  super.init(frame: frame, textContainer: textContainer)
  setupViews()
}

required init?(coder: NSCoder) {
  super.init(coder: coder)
}

private func setupViews() {
  //ATTRIBUTES & CONSTRAINTS DECLARED HERE ETC...

  self.isUserInteractionEnabled = true
  self.isMultipleTouchEnabled = true

  let swipeUp = UISwipeGestureRecognizer(target: self, action: #selector(hideError))
  swipeUp.direction = .up
  self.addGestureRecognizer(swipeUp)
}

@objc func hideError() {

  print(true)

}

Here is where I initialise the code on a different UIView.

let errorMessage = TopMessage()
self.addSubview(errorMessage)
errorMessage.translatesAutoresizingMaskIntoConstraints = false
errorMessage.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 20).isActive = true
errorMessage.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -20).isActive = true

let bottomConstraint = NSLayoutConstraint(item: errorMessage, attribute: .bottom, relatedBy: .equal, toItem: rootVC.view.safeAreaLayoutGuide, attribute: .top, multiplier: 1.0, constant: 0)
NSLayoutConstraint.activate([bottomConstraint])
errorMessage.sizeToFit()
errorMessage.text = "⚠️ Too many reset attempts. Try again later."

//Custom Animation function that I created, just makes constraint changes so the object goes from being hidden above the top of the view, to being constrained to the top safe area.
errorMessage.present(rootVC: rootVC, bottomConstraint: bottomConstraint, relatedItem: rootVC.view.safeAreaLayoutGuide)
  • Can you show where / how you're instantiating your text view? Are you using a storyboard or instantiating it in code? Is `setupViews` actually being called? – shim Jan 22 '20 at 21:05
  • Hi, yes setupViews does get called, the message appears as normal but just cant swipe gesture on it – Elliot Fisher Jan 23 '20 at 10:10

3 Answers3

0
required init?(coder: NSCoder) {
    super.init(coder: coder)
    setupViews()
}
alidevs
  • 11
  • 1
  • 1
  • 2
    Thank you for this code snippet, which might provide some limited, immediate help. A [proper explanation](https://meta.stackexchange.com/q/114762/349538) would greatly improve its long-term value by showing why this is a good solution to the problem and would make it more useful to future readers with other, similar questions. Please [edit] your answer to add some explanation, including the assumptions you’ve made. – Ismael Padilla Jan 22 '20 at 23:09
0

First your class should adopt UIGestureRecognizerDelegate and set your gesture as delegate. Then you should add a UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer function. And finally call setupViews() in required init.

class ErrorMessage : UITextView, UIGestureRecognizerDelegate {

override init(frame: CGRect, textContainer: NSTextContainer?) {
    super.init(frame: frame, textContainer: textContainer)
    setupViews()
}

required init?(coder: NSCoder) {
    super.init(coder: coder)
    swipeGestureRecognizer()
}

private func setupViews() {
    //ATTRIBUTES & CONSTRAINTS DECLARED HERE ETC...
    self.isUserInteractionEnabled = true
    self.isMultipleTouchEnabled = true
}

@objc func hideError() {
    print(true)
}

func swipeGestureRecognizer() {
    let swipeUp = UISwipeGestureRecognizer(target: self, action: #selector(hideError))
    swipeUp.delegate = self
    swipeUp.direction = .up
    self.addGestureRecognizer(swipeUp)
}

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
    return true
}

}

Worked for me, I hope that's gonna help you.

  • Thank you Dimitris for your answer. I have made the changes you mentioned, but now nothing is appearing? When I put setupViews() back into override init the object appears again but in required init nothing appears? – Elliot Fisher Jan 23 '20 at 10:09
  • Just to note I am initializing the TextView in code not by Storyboard – Elliot Fisher Jan 23 '20 at 10:11
  • I have added an edit to where I am initialising the object – Elliot Fisher Jan 23 '20 at 10:13
  • Maybe you should separate the setupViews function. Keep setting up UI elements on your setupViews that is been called inside override init and try making a method with your UISwipeGestureRecognizer and call this function inside required init. Let me know if that works. (I just edited my answer, you can check this out). – Dimitris Papaioannou Jan 23 '20 at 10:19
  • That didnt work, I put a print(true) in the edit to see if the swipeGestureRecognizer() function was being called, but when its in required init nothing is printed to the console suggesting its not being called? – Elliot Fisher Jan 23 '20 at 10:56
0

I found my answer in here.

UIButton not interacting during animation

I removed the animation that was being executed on the object at the time of interaction and the swipe began to work. Setting the alpha to change to 0.1 instead of 0.0 and setting the options to .allowUserInteraction, made the TextView interactable whilst animating.