didSelectRowAtIndexPath是否由于UI点击手势快速解决方案而未被调用? [英] didSelectRowAtIndexPath not being called because of UI tap Gesture Swift Solution?

查看:46
本文介绍了didSelectRowAtIndexPath是否由于UI点击手势快速解决方案而未被调用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经编写了自己的功能,可以在键盘出现时向上滚动文本字段.为了通过远离文本字段来关闭键盘,我创建了一个UITapGestureRecognizer,用于在远离文本字段时辞职第一响应者.

但是,在选择Auto完成的表中的一个条目时,DidselectRowatIndexpath不会被调用.取而代之的是,轻击手势识别器似乎正在被调用,只是辞职了第一响应者.

我猜想有某种方法可以告诉轻击手势识别器将轻击消息继续传递到UITableView,但我不知道它是什么.在objc中只有针对此的解决方案,而9年前堆栈溢出中的帖子,我想知道是否有对此的更新解决方案!谢谢,如果您想看看发生了什么,这是我的代码:

  ChatLogController类:UIViewController,UITextFieldDelegate,UITableViewDelegate,UITableViewDataSource,UIGestureRecognizerDelegate,UIImagePickerControllerDelegate,UINavigationControllerDelegate {var messages = [Message]()var user:用户?{didSet {watchMessages()}}@IBOutlet弱var tabelView:UITableView!@IBOutlet弱var messageTextField:UITextField!@IBOutlet弱var bottomViewHeightConstraint:NSLayoutConstraint!@IBOutlet弱var currentMessageRecieverImage:UIImageView!覆盖func viewDidLoad(){super.viewDidLoad()configureTableView()currentMessageRecieverImage.translatesAutoresizingMaskIntoConstraints = false;currentMessageRecieverImage.layer.cornerRadius = 30;currentMessageRecieverImage.layer.masksToBounds = truecurrentMessageRecieverImage.contentMode = .scaleAspectFill如果让currentMessageRecieverUser = user {currentMessageRecieverImage.loadImageUsingCacheWithUrlString(urlString:currentMessageRecieverUser.picURL!);打印(currentMessageRecieverUser.userName!)}tabelView.delegate =自我;tabelView.dataSource =自我;messageTextField.delegate =自我;让dragAwayFromTextGesture = UISwipeGestureRecognizer(target:self,action:#selector(handleTapAwayFromTextEdit))dragAwayFromTextGesture.direction = UISwipeGestureRecognizerDirection.downdragAwayFromTextGesture.delegate =自我;tabelView.addGestureRecognizer(dragAwayFromTextGesture)让dragBackToMessages = UISwipeGestureRecognizer(target:self,action:#selector(handleSwipeBackToMessages))dragBackToMessages.direction = UISwipeGestureRecognizerDirection.rightdragBackToMessages.delegate =自我;tabelView.addGestureRecognizer(dragBackToMessages)让TapAwayFromTextEditTapGesture = UITapGestureRecognizer(target:self,action:#selector(handleTapAwayFromTextEdit))tabelView.addGestureRecognizer(TapAwayFromTextEditTapGesture)}funcgestureRecognizer(_gestureRecognizer:UIGestureRecognizer,应该与其他GestureRecognizer同时识别:UIGestureRecognizer)->布尔{返回真}@objc func handleSwipeBackToMessages(){解雇(动画:false,完成:nil)}func watchMessages(){保护let uid = Auth.auth().currentUser?.uid else {返回;}//ref获取已登录的用户让ref = Database.database().reference().child("user-messages").child(uid)ref.observe(.childAdded){//获取所需的消息让messageId = snapshot.key让messagesRef = Database.database().reference().child("messages").child(messageId)messagesRef.observe(.value,其中:{守卫让dict = snapshot.value为?[String:AnyObject]其他{返回}让消息= Message()message.imageUrl = dict ["imageurl"]为?细绳message.fromId = dict ["fromid"]如?细绳message.text = dict ["text"] as?细绳message.timestamp = dict ["timestamp"] as?细绳message.toId = dict ["toid"]如?细绳如果message.chatPartnerId()== self.user?.toId {self.messages.append(message)}DispatchQueue.main.async {self.tabelView.reloadData()}})}}func tableView(_ tableView:UITableView,numberOfRowsInSection部分:Int)->诠释{返回messages.count;}func tableView(_ tableView:UITableView,cellForRowAt indexPath:IndexPath)->UITableViewCell {让cell = tableView.dequeueReusableCell(withIdentifier:"cellid",for:indexPath)为!CustomChatTableViewCell;让灰色= UIColor(红色:0.94,绿色:0.94,蓝色:0.94,alpha:1.0)让红色= UIColor(红色:1.00,绿色:0.22,蓝色:0.37,阿尔法:1.0)让message = messages [indexPath.item]如果message.toId == user?.toId {cell.messageBackground.backgroundColor =红色cell.messageLabel.textColor = UIColor.white}别的{cell.messageBackground.backgroundColor =灰色cell.messageLabel.textColor = UIColor.black}cell.messageLabel.text = message.text如果message.imageUrl!= nil {//打印(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 = .scaleAspectFillcell.messageLabel.isHidden = truecell.messageBackground.isHidden = true;}别的{cell.messageImageView.isHidden = true;cell.selectionStyle = UITableViewCellSelectionStyle.nonecell.messageLabel.isHidden = falsecell.messageBackground.isHidden = false;}返回单元}@objc func handleTapAwayFromTextEdit(){//print(轻按远离文本编辑运行的位置")messageTextField.endEditing(true)}@IBAction func backToMessageListPressed(_ sender:Any){解雇(动画:false,完成:nil)}@IBAction func infoButtonPressed(_ sender:Any){}//将文本保存到火力基地@IBAction func sendButtonPressed(_ sender:Any){handleSendMessageToDataBase()}func handleSendMessageToDataBase(){让ref = Database.database().reference().child("messages")//在firebase中为唯一文本创建列表所需让childRef = ref.childByAutoId()如果messageTextField.text ==""{返回}如果让message = messageTextField.text {让toID = user!.toId!让fromId = Auth.auth().currentUser!.uidlet timeStamp:Int = Int(Int(NSDate().timeIntervalSince1970))打印(时间戳)let值= [文本":消息,"toid";:toID,时间戳";:" \(timeStamp)","fromid":fromId]childRef.updateChildValues(values,withCompletionBlock:{(错误,ref)在如果错误!=无{打印(错误!)返回}让userMessagesref = Database.database().reference().child("user-messages").child(fromId)让messageID = childRef.keyuserMessagesref.updateChildValues([messageID:1])让receiveUserMessageRef = Database.database().reference().child("user-messages").child(toID)receiverUserMessageRef.updateChildValues([messageID:1])})}messageTextField.text ="messageTextField.endEditing(true)}@IBAction func sendImageButtonPressed(_ sender:Any){handleSendImage()}func tableView(tableView:UITableView !, didSelectRowAtIndexPath indexPath:NSIndexPath!){print(您选择了单元格#\(indexPath.row)!")}func handleSendImage(){让imagePickerController = UIImagePickerController()imagePickerController.delegate =自我存在(imagePickerController,动画:true,完成:nil)}func imagePickerControllerDidCancel(_ picker:UIImagePickerController){关闭(动画:true,完成:nil)}func imagePickerController(__ picker:UIImagePickerController,didFinishPickingMediaWithInfo信息:[String:任何]){var selectedImageFromPicker:UIImage?如果让editedImage = info ["UIImagePickerControllerEditedImage"]为?UIImage {selectedImageFromPicker = editedImage}否则是否让originalImage = info ["UIImagePickerControllerOriginalImage"]为?UIImage {selectedImageFromPicker = originalImage}如果让selectedImage = selectedImageFromPicker {uploadToFireBaseUsingSelectedImage(selectedImage:selectedImage)}关闭(动画:true,完成:nil)}私人函式uploadToFireBaseUsingSelectedImage(selectedImage:UIImage){让imageName = NSUUID().uuidString让refToStorage = Storage.storage().reference().child("message_images").child(imageName)如果让uploadData = UIImageJPEGRepresentation(selectedImage,0.2){refToStorage.putData(uploadData,元数据:无,完成:{(metaData,错误)在如果错误!=无{打印(在chatlogcontroller中发送时无法上传Firebase图像")打印(错误!)返回}如果让imageURL = metaData?.downloadURL()?. absoluteString {self.sendMessageWithImageURL(imageURL:imageURL)}})}}私人功能sendMessageWithImageURL(imageURL:String){让ref = Database.database().reference().child("messages")//在firebase中为唯一文本创建列表所需让childRef = ref.childByAutoId()让toID = user!.toId!让fromId = Auth.auth().currentUser!.uidlet timeStamp:Int = Int(Int(NSDate().timeIntervalSince1970))打印(时间戳)let值= ["imageurl":imageURL,"toid";:toID,时间戳";:" \(timeStamp)","fromid":fromId]childRef.updateChildValues(values,withCompletionBlock:{(错误,ref)在如果错误!=无{打印(错误!)返回}让userMessagesref = Database.database().reference().child("user-messages").child(fromId)让messageID = childRef.keyuserMessagesref.updateChildValues([messageID:1])让receiveUserMessageRef = Database.database().reference().child("user-messages").child(toID)receiverUserMessageRef.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 =自我;tabelView.dataSource =自我;tabelView.register(UINib(nibName:"MessageCell",bundle:nil),forCellReuseIdentifier:"customMessageCell");tabelView.allowsSelection = true;}覆盖func viewDidDisappear(_动画:布尔){super.viewDidDisappear(动画)NotificationCenter.default.removeObserver(self);}func tableView(_ tableView:UITableView,heightForRowAt indexPath:IndexPath)->CGFloat {让message = messages [indexPath.item]如果message.imageUrl!= nil {回报200}return(CGFloat((message.text?.count)!+ 70))}func tableView(_ tableView:UITableView,estimateHeightForRowAt indexPath:IndexPath)->CGFloat {返回80}func textFieldShouldReturn(_ textField:UITextField)->布尔{handleSendMessageToDataBase()返回真} 

}

解决方案

解决方案是将 TapAwayFromTextEditTapGesture 的属性 cancelsTouchesInView 设置为 false .这将使它直接与表格视图保持联系.

关于此媒体资源的Apple文档(我强调):

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

I have written my own function to scroll text fields up when the keyboard shows up. In order to dismiss the keyboard by tapping away from the text field, I've created a UITapGestureRecognizer that takes care of resigning first responder on the text field when tapping away.

However, when selecting one of the entries in the auto completed table, didSelectRowAtIndexPath does not get called. Instead, it seems that the tap gesture recognizer is getting called and just resigns first responder.

I'm guessing there's some way to tell the tap gesture recognizer to keep passing the tap message on down to the UITableView, but I can't figure out what it is. There are only solutions for this in objc and posts from over 9 years ago on stack overflow , I was wondering if there was an updated solution to this! Thank you , Here is my code if you would like to see whats going on :

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
}

}

解决方案

The solution is to set the property cancelsTouchesInView of your TapAwayFromTextEditTapGesture to false. This will cause it to pass on touches to the table view.

From the Apple documentation on this property (with my emphasis):

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.

这篇关于didSelectRowAtIndexPath是否由于UI点击手势快速解决方案而未被调用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆