由于UI点击手势Swift解决方案,没有调用didSelectRowAtIndexPath?

嘿伙计们我很快就开心了,所以请善待! 当键盘出现时,我编写了自己的函数来向上滚动文本字段。 为了通过点击文本字段来关闭键盘,我创建了一个UITapGestureRecognizer,它可以在点击时关注文本字段上的第一个响应者。

但是,在自动完成表中选择其中一个条目时,不会调用didSelectRowAtIndexPath。 相反,似乎轻敲手势识别器正在被调用并且只是辞职第一响应者。

我猜是有一种方法可以告诉轻敲手势识别器继续将点击消息传递到UITableView,但我无法弄清楚它是什么。 在9年前的堆栈溢出的objc和post中只有解决方案,我想知道是否有更新的解决方案! 谢谢,如果你想了解最新情况,这是我的代码:

class ChatLogController : UIViewController, UITextFieldDelegate , UITableViewDelegate , UITableViewDataSource, UIGestureRecognizerDelegate, UIImagePickerControllerDelegate ,UINavigationControllerDelegate { var messages = [Message]() var user : User?{ didSet{ observeMessages() } } @IBOutlet weak var tabelView: UITableView! @IBOutlet weak var messageTextField: UITextField! @IBOutlet weak var bottomViewHeightConstraint: NSLayoutConstraint! @IBOutlet weak var currentMessageRecieverImage: UIImageView! override func viewDidLoad() { super.viewDidLoad() configureTableView() currentMessageRecieverImage.translatesAutoresizingMaskIntoConstraints = false; currentMessageRecieverImage.layer.cornerRadius = 30; currentMessageRecieverImage.layer.masksToBounds = true currentMessageRecieverImage.contentMode = .scaleAspectFill if let currentMessageRecieverUser = user{ currentMessageRecieverImage.loadImageUsingCacheWithUrlString(urlString: currentMessageRecieverUser.picURL!); print(currentMessageRecieverUser.userName!) } tabelView.delegate = self; tabelView.dataSource = self; messageTextField.delegate = self; let dragAwayFromTextGesture = UISwipeGestureRecognizer(target: self, action: #selector(handleTapAwayFromTextEdit)) dragAwayFromTextGesture.direction = UISwipeGestureRecognizerDirection.down dragAwayFromTextGesture.delegate = self; tabelView.addGestureRecognizer(dragAwayFromTextGesture) let dragBackToMessages = UISwipeGestureRecognizer(target: self, action: #selector(handleSwipeBackToMessages)) dragBackToMessages.direction = UISwipeGestureRecognizerDirection.right dragBackToMessages.delegate = self; tabelView.addGestureRecognizer(dragBackToMessages) let TapAwayFromTextEditTapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTapAwayFromTextEdit)) tabelView.addGestureRecognizer(TapAwayFromTextEditTapGesture) } func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { return true } @objc func handleSwipeBackToMessages(){ dismiss(animated: false, completion: nil) } func observeMessages(){ guard let uid = Auth.auth().currentUser?.uid else{ return; } // ref gets user that is logged in let ref = Database.database().reference().child("user-messages").child(uid) ref.observe(.childAdded) { (snapshot) in // gets needed messages let messageId = snapshot.key let messagesRef = Database.database().reference().child("messages").child(messageId) messagesRef.observe(.value, with: { (snapshot) in guard let dict = snapshot.value as? [String : AnyObject] else{ return } let message = Message() message.imageUrl = dict["imageurl"] as? String message.fromId = dict["fromid"] as? String message.text = dict["text"] as? String message.timestamp = dict["timestamp"] as? String message.toId = dict["toid"] as? String if message.chatPartnerId() == self.user?.toId{ self.messages.append(message) } DispatchQueue.main.async { self.tabelView.reloadData() } }) } } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return messages.count; } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "cellid" , for: indexPath) as! CustomChatTableViewCell; let gray = UIColor(red:0.94, green:0.94, blue:0.94, alpha:1.0) let red = UIColor(red:1.00, green:0.22, blue:0.37, alpha:1.0) let message = messages[indexPath.item] if message.toId == user?.toId{ cell.messageBackground.backgroundColor = red cell.messageLabel.textColor = UIColor.white } else{ cell.messageBackground.backgroundColor = gray cell.messageLabel.textColor = UIColor.black } cell.messageLabel.text = message.text if message.imageUrl != nil{ //print(message.imageUrl!) // cell.messageImageView.image = UIImage(named : "user.jpg") cell.messageImageView.loadImageUsingCacheWithUrlString(urlString: message.imageUrl!) //print(cell.messageImageView.image.debugDescription) cell.messageImageView.isHidden = false; cell.messageImageView.translatesAutoresizingMaskIntoConstraints = false; cell.messageImageView.contentMode = .scaleAspectFill cell.messageLabel.isHidden = true cell.messageBackground.isHidden = true; } else { cell.messageImageView.isHidden = true; cell.selectionStyle = UITableViewCellSelectionStyle.none cell.messageLabel.isHidden = false cell.messageBackground.isHidden = false; } return cell; } @objc func handleTapAwayFromTextEdit(){ //print("handle tap away from text edit running ") messageTextField.endEditing(true) } @IBAction func backToMessageListPressed(_ sender: Any) { dismiss(animated: false, completion: nil) } @IBAction func infoButtonPressed(_ sender: Any) { } // saves text to fire base @IBAction func sendButtonPressed(_ sender: Any) { handleSendMessageToDataBase() } func handleSendMessageToDataBase(){ let ref = Database.database().reference().child("messages") // needed for making list in firebase for unique texts let childRef = ref.childByAutoId() if messageTextField.text == ""{ return } if let message = messageTextField.text{ let toID = user!.toId! let fromId = Auth.auth().currentUser!.uid let timeStamp : Int = Int(Int(NSDate().timeIntervalSince1970)) print(timeStamp) let values = ["text" : message , "toid" : toID , "timestamp" : "\(timeStamp)" , "fromid" : fromId] childRef.updateChildValues(values, withCompletionBlock: { (error, ref) in if error != nil{ print(error!) return } let userMessagesref = Database.database().reference().child("user-messages").child(fromId) let messageID = childRef.key userMessagesref.updateChildValues([messageID: 1]) let recipientUserMessageRef = Database.database().reference().child("user-messages").child(toID) recipientUserMessageRef.updateChildValues([messageID: 1]) }) } messageTextField.text = "" messageTextField.endEditing(true) } @IBAction func sendImageButtonPressed(_ sender: Any) { handleSendImage() } func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!) { print("You selected cell #\(indexPath.row)!") } func handleSendImage(){ let imagePickerController = UIImagePickerController() imagePickerController.delegate = self present(imagePickerController, animated: true, completion: nil) } func imagePickerControllerDidCancel(_ picker: UIImagePickerController) { dismiss(animated: true, completion: nil) } func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) { var selectedImageFromPicker : UIImage? if let editedImage = info["UIImagePickerControllerEditedImage"] as? UIImage{ selectedImageFromPicker = editedImage } else if let originalImage = info["UIImagePickerControllerOriginalImage"] as? UIImage{ selectedImageFromPicker = originalImage } if let selectedImage = selectedImageFromPicker{ uploadToFireBaseUsingSelectedImage(selectedImage : selectedImage) } dismiss(animated: true, completion: nil) } private func uploadToFireBaseUsingSelectedImage(selectedImage : UIImage){ let imageName = NSUUID().uuidString let refToStorage = Storage.storage().reference().child("message_images").child(imageName) if let uploadData = UIImageJPEGRepresentation(selectedImage, 0.2){ refToStorage.putData(uploadData, metadata: nil, completion: { (metaData, error) in if error != nil{ print("failed to upload firebase image when sending in chatlogcontroller") print(error!) return } if let imageURL = metaData?.downloadURL()?.absoluteString{ self.sendMessageWithImageURL(imageURL: imageURL) } }) } } private func sendMessageWithImageURL(imageURL : String){ let ref = Database.database().reference().child("messages") // needed for making list in firebase for unique texts let childRef = ref.childByAutoId() let toID = user!.toId! let fromId = Auth.auth().currentUser!.uid let timeStamp : Int = Int(Int(NSDate().timeIntervalSince1970)) print(timeStamp) let values = ["imageurl" : imageURL , "toid" : toID , "timestamp" : "\(timeStamp)" , "fromid" : fromId] childRef.updateChildValues(values, withCompletionBlock: { (error, ref) in if error != nil{ print(error!) return } let userMessagesref = Database.database().reference().child("user-messages").child(fromId) let messageID = childRef.key userMessagesref.updateChildValues([messageID: 1]) let recipientUserMessageRef = Database.database().reference().child("user-messages").child(toID) recipientUserMessageRef.updateChildValues([messageID: 1]) }) } func textFieldDidBeginEditing(_ textField: UITextField) { UIView.animate(withDuration: 0.2, animations:{ self.bottomViewHeightConstraint.constant = 308; self.view.layoutIfNeeded() }) } func textFieldDidEndEditing(_ textField: UITextField) { UIView.animate(withDuration: 0.2, animations:{ self.bottomViewHeightConstraint.constant = 50; self.view.layoutIfNeeded() }) } func configureTableView() { tabelView.delegate = self; tabelView.dataSource = self; tabelView.register(UINib(nibName: "MessageCell" , bundle : nil), forCellReuseIdentifier: "customMessageCell"); tabelView.allowsSelection = true; } override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) NotificationCenter.default.removeObserver(self); } func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { let message = messages[indexPath.item] if message.imageUrl != nil{ return 200 } return (CGFloat((message.text?.count)! + 70) ) } func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat { return 80 } func textFieldShouldReturn(_ textField: UITextField) -> Bool { handleSendMessageToDataBase() return true } 

}

解决方案是将cancelsTouchesInView的属性cancelsTouchesInView设置为false 。 这将导致它将触摸传递给表视图。

从这个属性的Apple文档 (我强调):

当此属性为true(默认值)且接收器识别其手势时,挂起的该手势的触摸 不会传递到视图,并且通过发送到视图的touchesCancelled(_:with :)消息取消先前传递的触摸。 如果手势识别器不识别其手势或者该属性的值为假,则视图接收多点触摸序列中的所有触摸

另外两种方法:

  1. UITextViewDelegate ,在开始编辑时启用手势识别器,在结束编辑时禁用手势识别器。 您还可以在键盘事件处理方法中启用它,并在手势识别器调用的方法中禁用它。

  2. 将手势识别器分配给代表,并在代表中询问手势识别器是否应该接收触摸事件时检查键盘是否已启动。