didSelectRowAtIndexPath 没有因为 UI 点击 Gesture Swift 解决方案而被调用?

Zac*_*117 4 uitableview ios swift

我已经编写了自己的函数来在键盘出现时向上滚动文本字段。为了通过点击远离文本字段来关闭键盘,我创建了一个 UITapGestureRecognizer,它负责在点击离开时退出文本字段上的第一响应者。

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

我猜有一些方法可以告诉点击手势识别器继续将点击消息传递给 UITableView,但我不知道它是什么。在 objc 和 9 多年前关于堆栈溢出的帖子和帖子中只有解决方案,我想知道是否有更新的解决方案!谢谢,如果您想看看发生了什么,这是我的代码:

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
}
Run Code Online (Sandbox Code Playgroud)

}

sho*_*ing 6

解决方案是将cancelsTouchesInView您的属性设置TapAwayFromTextEditTapGesturefalse. 这将导致它传递触摸到表格视图。

来自关于此属性Apple 文档(我的重点):

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