UITapGestureRecognizer breaks UITableView didSelectRowAtIndexPath in SearchField Class in Swift? - ios

I am using this library for SearchText Field
https://github.com/apasccon/SearchTextField
Here is my Code :
override func viewDidLoad() {
super.viewDidLoad()
self.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: Selector("dismissKeyboard")))
}
func dismissKeyboard()
{
ClientList.resignFirstResponder()
self.view.endEditing(true)
}
Dismiss of keyboard is working but the didSelectRowAtIndexPath is not getting called so i am not able to select anything
Image for Reference :
Partial Solution I Done:
func hideKeyboard(gestureRecognizer: UIGestureRecognizer) {
let point = gestureRecognizer.locationInView(ClientList.tableView)
let indexPath = ClientList.tableView!.indexPathForRowAtPoint(point)
if indexPath != nil {
return
}
if ClientList.becomeFirstResponder() {
ClientList.resignFirstResponder()
}
}
But now issue is i have other list too , how can i implement for other list ?

You can solve this issue like this
ViewDidLoad
self.tap = UITapGestureRecognizer(target: self, action: "viewTapped:")
self.tap.delegate = self
self.view.addGestureRecognizer(self.tap)
Function
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
if touch.view != nil && touch.view!.isDescendantOfView(self.tableView) {
return false
}
return true
}

Who's the target of the gesture? I think it should be the list since it is what you tap and it is above the view

let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "dismissKeyboard")
view.addGestureRecognizer(tap)
Add this to viewDidLoad
And add this function
func dismissKeyboard() {
//Causes the view (or one of its embedded text fields) to resign the first responder status.
view.endEditing(true)
}

Related

How to dismiss UISearchBar keyboard without effecting other functionalities?

is how my screen looks like..
Now my code for dismissing the keyboard when the use of searchbar is over:
override func viewDidLoad() {
super.viewDidLoad()
let tap = UITapGestureRecognizer(target: self, action: #selector(handleTap))
view.addGestureRecognizer(tap)
}
#objc func handleTap() {
searchbar.resignFirstResponder()
}
By this my keyboard is getting dismissed but whenever using this, the tableview DidSelectRowAt is no more working (Though there is no error or warning). I am confused that what is the problem exactly. Please help! Thanks is advance..
Set cancelsTouchesInView to false, for detailed explanation: link
extension UIViewController {
func hideKeyboard() {
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(UIViewController.dismissKeyboard))
tap.cancelsTouchesInView = false
view.addGestureRecognizer(tap)
}
#objc
func dismissKeyboard() {
view.endEditing(true)
}
}
Usage:
call hideKeyboard() in the viewDidLoad of the controller.

Dismiss Keyboard And Allow Button Gesture Recognizers Swift iOS

I'm using this code to hide the keyboard when the user taps anywhere on the screen outside of the TextView:
override func viewDidLoad() {
super.viewDidLoad()
//Looks for single or multiple taps.
let tap = UITapGestureRecognizer(target: self, action: #selector(UIInputViewController.dismissKeyboard))
tap.delegate = self
//Uncomment the line below if you want the tap not not interfere and cancel other interactions.
tap.cancelsTouchesInView = false
view.addGestureRecognizer(tap)
}
//Calls this function when the tap is recognized.
#objc func dismissKeyboard() {
//Causes the view (or one of its embedded text fields) to resign the first responder status.
view.endEditing(true)
}
public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
if touch.view is UIButton {
return false
}
return true
}
The problem is I have a UIButton in this view as well - when I tap on the button, the button's gesture recognizer function is not called. Instead, dismissKeyboard is called. I already tried the suggestion of using tap.cancelsTouchesInView = false as well as the shouldReceive method, but neither of them work - in the shouldReceive method, when I tap on the button, the class of touch.view is UIView.
Does anybody know how to allow the user to hide the keyboard when clicking anywhere on screen, but also allow button action handlers to execute?
I fixed this using the following code:
I detect the location of the user's touch
I check if the touch is in the frame of each of the two buttons in my UIView
If this is true, I manually call the button handler and return false from the method
public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
if let view = self.view as? MyViewControllersView {
let location = touch.location(in: self.view)
if view.saveButton.frame.contains(location) {
view.saveHit()
return false
} else if view.scanButton.frame.contains(location) {
view.scanHit()
return false
}
}
return true
}
it works for me, please check out
//MARK:- View Lyfe cycle
override func viewDidLoad() {
super.viewDidLoad()
IQKeyboardManager.shared().isEnableAutoToolbar = false
// IQKeyboardManager.shared().disabledToolbarClasses = self
IQKeyboardManager.shared().isEnabled = false
self.keyboardWillShowAndHide()
initializeHideKeyboard()
}
//MARK:- KayBoard Handling...
//MARK:- Init Hide KeyBoard...
func initializeHideKeyboard(){
//Declare a Tap Gesture Recognizer which will trigger our dismissMyKeyboard() function
let tap: UITapGestureRecognizer = UITapGestureRecognizer(
target: self,
action: #selector(dismissMyKeyboard))
//Add this tap gesture recognizer to the parent view
view.addGestureRecognizer(tap)
}
//MARK:- Dismissing Keyboard...
#objc func dismissMyKeyboard(){
//endEditing causes the view (or one of its embedded text fields) to resign the first responder status.
//In short- Dismiss the active keyboard.
view.endEditing(true)
}
//MARK:- Kayboard Hide and Show...
func keyboardWillShowAndHide(){
NotificationCenter.default.addObserver(
self,
selector: #selector(keyboardWillShow),
name: UIResponder.keyboardWillShowNotification,
object: nil
)
NotificationCenter.default.addObserver(
self,
selector: #selector(keyboarddidHide),
name: UIResponder.keyboardWillHideNotification,
object: nil
)
}
//MARK:- KeyBoard Will Show
#objc func keyboardWillShow(_ notification: Notification) {
self.arrConversationList.count
if let keyboardFrame: NSValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue {
let keyboardRectangle = keyboardFrame.cgRectValue
let keyboardHeight = keyboardRectangle.height
self.ChatBottomConstraint.constant = keyboardHeight - self.bottomLayoutGuide.length
DispatchQueue.main.asyncAfter(deadline: .now()+0.1, execute: {
if self.arrConversationList.count > 0 {
let indexPath = NSIndexPath(row: self.arrConversationList.count-1, section: 0)
self.ConversationTblref.scrollToRow(at: indexPath as IndexPath, at: .bottom, animated: true)
}
})
self.tableviewbottomconstraintref.constant = 0
ConversationTblref.reloadData()
}
}
//MARK:- KeyBoard Will Hide
#objc func keyboarddidHide(_ notification: Notification) {
self.tableviewbottomconstraintref.constant = 0
self.ChatBottomConstraint.constant = 0
ConversationTblref.reloadData()
}
//MARK:- View Disappear for handleing kayboard...
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(true)
IQKeyboardManager.shared().isEnableAutoToolbar = true
IQKeyboardManager.shared().isEnabled = true
NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
}
override func viewDidDisappear(_ animated: Bool) {
}

UIGesturerecognizer is not working on UIView

When I am tapping on UIView but Gesture is not working.
override func viewDidLoad() {
super.viewDidLoad()
let tap = UITapGestureRecognizer(target: self, action: #selector(self.handleTap(_:)))
viewForSHadow.isUserInteractionEnabled = true
viewForSHadow.addGestureRecognizer(tap)
// Do any additional setup after loading the view.
}
func handleTap(_sender: UITapGestureRecognizer) {
print("---------View Tapped--------")
viewForSHadow.isHidden = true
viewForAlert.isHidden = true
}
I just want to perform this action on UIView tap.
You may check in the debug view hierarchy if anything with alpha = 0 is overlapping your viewForSHadow.
You have to implement as follows:
class ViewController: UIViewController, UIGestureRecognizerDelegate {
...
override func viewDidLoad() {
super.viewDidLoad()
let tap = UITapGestureRecognizer(target: self, action: #selector(handleTap(_sender:)))
viewForSHadow.isUserInteractionEnabled = true
viewForSHadow.addGestureRecognizer(tap)
}
#objc func handleTap(_sender: UITapGestureRecognizer) {
print("---------View Tapped--------")
viewForSHadow.isHidden = true
viewForAlert.isHidden = true
}
...
}
Your code is more than enough to have working UIGestureRecognizer, you should check some other stuff like, is there something else that can consume the user interaction. And also to check if you use
isUserInteractionEnabled = false
to some parent view of viewForSHadow.
You have to use UIGestureRecognizerDelegate
let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleDismiss))
tapRecognizer.delegate = self
blackView.addGestureRecognizer(tapRecognizer)
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
return true
}
#objc func handleDismiss() {
print("handleDismiss")
}
Reference
Don't forget to set the UIGestureRecognizerDelegate in your class
You need to mention numberOfTapsRequired property of the UITapGestureRecognizer.
override func viewDidLoad() {
super.viewDidLoad()
let tap = UITapGestureRecognizer(target: self, action: #selector(handleTapGesture(_sender:)))
tap.numberOfTapsRequired = 1
viewForSHadow.isUserInteractionEnabled = true
viewForSHadow.addGestureRecognizer(tap)
}
#objc func handleTapGesture(_sender: UITapGestureRecognizer) {
print("---------View Tapped--------")
// Why are you hiding this view **viewForSHadow**
viewForSHadow.isHidden = true
viewForAlert.isHidden = true
}
Also, make sure you are not doing viewForSHadow.isUserInteractionEnabled = false anywhere in the code.
First of all you code doesn't compile. The handleTap(_:) signature must be like:
#objc func handleTap(_ sender: UITapGestureRecognizer) {
print("---------View Tapped--------")
}
Secondly, you need to first try with the minimal code in a separate project. And by minimal code I mean what you've added in the question.
class ViewController: UIViewController {
#IBOutlet weak var viewForSHadow: UIView!
override func viewDidLoad() {
super.viewDidLoad()
let tap = UITapGestureRecognizer(target: self, action: #selector(self.handleTap(_:)))
viewForSHadow.addGestureRecognizer(tap)
}
#objc func handleTap(_ sender: UITapGestureRecognizer) {
print("---------View Tapped--------")
}
}
Try with just the above code and see if you can get it working. The above code is working well at my end without any delegate or numberOfTaps.

make hitTest(_:with:) function return UIButton

I have a view that added some UIButton.
given a CGPoint how can I get the button laid on.
sample code
let location = tapRecognizer.location(in: view)
let tapView = view.hitTest(location, with: nil)
the code below won't work how can I get the UIbutton form tapView
if let button = tapView as? UIButton {
print("text")
}
help appreciated
While adding button to the view add target to the button and assign a different tag to each button and perform action according to the tag
For the this purpose you can use the gesture delegate like
Example:-
func addGestureOnContentView () -> Void {
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(ExploreViewController.hideTableView))
tapGesture.delegate = self
self.view.addGestureRecognizer(tapGesture)
}
Now use gesture delegate like :-
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
if gestureRecognizer is UITapGestureRecognizer {
if (touch.view?.isDescendant(of: UIButton))! {
return false //Perform your task in this block
}
}
return true
}

Swift 3 UITapGestureRecognizer not receiving tap

I want to add a gesture recognizer to one of my views to detect taps,
here is my code:
class DateTimeContainer: UIView, UIGestureRecognizerDelegate {
override func awakeFromNib() {
let gesture = UITapGestureRecognizer(target: self, action: #selector(self.onTap))
gesture.delegate = self
self.addGestureRecognizer(gesture)
}
func onTap(_ gestureRecognizer: UITapGestureRecognizer) {
openDatePicker()
}
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
if touch.view?.tag != self.datePickerTag && !self.isDatePickerOpen() {
return true
}
return false
}
}
When I tap on my view the code enters into the gestureRecognizer shouldReceive method and enters the condition for which it returns true.
But the onTap method is never called, can someone tell me why?
EDIT
Adding self.isUserInteractionEnabled = true I managed to get it working.
But it had a strange behaviour: it was like it received the tap only in the main view and not in subviews.
So to make it simple I solved by adding a button inside my view and by using:
self.button?.addTarget(self, action: #selector(onTap), for: .touchUpInside)
You may have forgotten to do this:
self.isUserInteractionEnabled = true
Also, typically the UIViewController subclass is usually the target and contains the method used for the tap gesture.
You don't need to set a delegate for a tap gesture (usually)
You can You Gesture
let recognizer = UITapGestureRecognizer(target: self,action:#selector(self.handleTap(recognizer:)))
userImage.isUserInteractionEnabled = true
recognizer.delegate = self as? UIGestureRecognizerDelegate
userImage.addGestureRecognizer(recognizer)
And method call selector
func handleTap(recognizer:UITapGestureRecognizer) {
// do your coding here on method
}
Try Writing the codes
let gesture = UITapGestureRecognizer(target: self, action: #selector(self.onTap))
gesture.delegate = self
self.addGestureRecognizer(gesture)
inside init block not in awakeFromNib()
I noticed that you are adding your gesture on a UIView. As such, at that ViewController where you have added this ContainerView, inside the viewDidLoad method, add this line of code.
override func viewDidLoad() {
super.viewDidLoad()
self.YourContainerView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(YourCurrentViewController.openDatePicker())))
self.YourContainerView.isUserInteractionEnabled = true
}
Note. Do not forget to add isUserInteractionEnabled to true.

Resources