ios - didSelectRowAtIndexPath 没有被调用,因为 UI 点击手势 Swift 解决方案?

标签 ios swift uitableview

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

However, when selecting one of the entries in the auto completed table, didSelectRowAtIndexPath does not get called.相反,点击手势识别器似乎正在被调用并且只是辞去了第一响应者。

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

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
}

最佳答案

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

来自Apple documentation on this property (我强调):

When this property is true (the default) and the receiver recognizes its gesture, the touches of that gesture that are pending are not delivered to the view and previously delivered touches are cancelled through a touchesCancelled(_:with:) message sent to the view. If a gesture recognizer doesn’t recognize its gesture or if the value of this property is false, the view receives all touches in the multi-touch sequence.

关于ios - didSelectRowAtIndexPath 没有被调用,因为 UI 点击手势 Swift 解决方案?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47646425/

相关文章:

ios - 选项卡栏 Controller - 在选项卡栏中添加更多项目看起来很乱

ios - 如何在 Swift 中从 Firestore 读取多个自定义对象

ios - 放大 UIView 而不会像素化

swift - 自定义annotationView标签重叠(导致MKMapView内存泄露)

ios - 使用自动布局自定义 UITableViewCell 的 subview - 没有 xibs,全部在代码中

ios - Flutter 应用程序总是在 ios 模拟器中运行时崩溃

swift - 无法建立 CKRecord 变量 - 准备继续

ios - 从 json 加载数据后在 TableView 上创建标签

ios - 在 iOS 中重新加载 tableview 部分时出现残像

ios - "An error occurred when accessing the keychain"