UITextfield 使用插入在 UITableView 中显示空行

Posted

技术标签:

【中文标题】UITextfield 使用插入在 UITableView 中显示空行【英文标题】:UITextfield showing empty row in UITableView using insert 【发布时间】:2019-05-16 00:54:17 【问题描述】:

我的应用程序中有一个聊天功能,当用户输入新文本时,它会立即更新表格。不幸的是,当用户输入文本时,它会在 uitableview 中显示任何空行。当我退出屏幕并返回时,新值现在在表的末尾。因此,即使它在 uitableview 中显示一个空行,它也会将实际值提交给数据库。

class ConversationViewController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate, UITableViewDelegate, UITableViewDataSource, UITextViewDelegate 
//var user = NSDictionary()
var messages = NSDictionary()
var hhmessages = [AnyObject]()
//var messages: [Message] = []
var pictures = [UIImage]()

var avas = [UIImage]()
var avaURL = [String]()
var isLoading = false
var skip = 0
var limit = 50
var images = [UIImage]()
var incoming: [Int] = []
var comments = [String]()
var ids = [String]()

@IBOutlet var replyTxt: UITextView!

@IBOutlet var replyTxt_height: NSLayoutConstraint!

@IBOutlet var replyTxt_bottom: NSLayoutConstraint!

@IBOutlet var replyBtn: UIButton!
var commentsTextView_bottom_identity = CGFloat()


@IBOutlet var tableView: UITableView!

// Table View here + basic configuration

override func viewDidLoad() 
    super.viewDidLoad()

    // dynamic cell height
    tableView.dataSource = self
    tableView.delegate = self
    tableView.rowHeight = UITableViewAutomaticDimension
    tableView.estimatedRowHeight = 200

    loadPosts()

    replyTxt.layer.cornerRadius = replyTxt.bounds.width / 50
    replyTxt.backgroundColor = UIColor.clear
    replyTxt.layer.borderColor = UIColor.gray.cgColor
    replyTxt.layer.borderWidth = 1.0

    let username = messages["sender"] as? String

    self.navigationItem.title = username



// TABLEVIEW

// Number os cells
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 

    return hhmessages.count


func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    let colorSmoothGray = UIColor(red: 229/255, green: 229/255, blue: 234/255, alpha: 1)
    let colorBrandBlue = UIColor(red: 148 / 255, green: 33 / 255, blue: 147 / 255, alpha: 1)
    let pictureURL = hhmessages[indexPath.row]["uploadpath"] as? String

    // no picture in the post
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! ConversationCell

        cell.transform = CGAffineTransform(rotationAngle: CGFloat(Double.pi))

        // shortcuts
        let hhpost = hhmessages[indexPath.row]
        let text = hhpost["messagetext"] as? String

            cell.messageLbl.text = text

        return cell




// func of loading posts from server
@objc func loadPosts() 
    //isLoading = true
    let me = user!["username"] as! String
    let meid = user!["id"] as! String
    print(meid)
    print(me)
    //print(username)
    let uuid = messages["uuid"] as! String
    print(uuid)

    // accessing php file via url path
    let url = URL(string: "http://localhost/message.php")!

    // pass information to php file
    let body = "username=\(me)&uuid=\(uuid)&recipient_id=\(meid)"
    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    request.httpBody = body.data(using: String.Encoding.utf8)
    tableView.transform = CGAffineTransform(rotationAngle: -(CGFloat)(Double.pi));

    // launch session
    URLSession.shared.dataTask(with: request)  (data, response, error) in
        DispatchQueue.main.async 

            // no error of accessing php file
            // error occured
            if error != nil 
                Helper().showAlert(title: "Server Error", message: error!.localizedDescription, in: self)
                //self.isLoading = false
                return
            

            do 
                // access data - safe mode
                guard let data = data else 
                    Helper().showAlert(title: "Data Error", message: error!.localizedDescription, in: self)
                    //self.isLoading = false
                    return
                
                // getting content of $returnArray variable of php file
                let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? NSDictionary

                // accessing json data - safe mode
                guard let posts = json?["messages"] as? [NSDictionary] else 
                    //self.isLoading = false
                    return
                

                // assigning all successfully loaded posts to our Class Var - posts (after it got loaded successfully)
                self.hhmessages = posts

                self.tableView.reloadData()

                // scroll to the latest index (latest cell -> bottom)
                let indexPath = IndexPath(row: self.hhmessages.count - 1, section: 0)
                self.tableView.scrollToRow(at: indexPath, at: .bottom, animated: true)
              //  self.isLoading = false

             catch 
                Helper().showAlert(title: "JSON Error", message: error.localizedDescription, in: self)
                //self.isLoading = false
                return
            

        
        .resume()




// function sending requset to PHP to uplaod a file
func uploadPost() 
    // validating vars before sending to the server
    guard let user_id = user?["id"] as? String, let username = user?["username"] as? String, let avaPath = user?["ava"] else 

        // converting url string to the valid URL
        if let url = URL(string: user?["ava"] as! String) 

            // downloading all data from the URL
            guard let data = try? Data(contentsOf: url) else 
                return
            

            // converting donwloaded data to the image
            guard let image = UIImage(data: data) else 
                return
            

            // assigning image to the global var
            let currentUser_ava = image
        

        return
    

    let user_id_int = Int(user_id)!
    let messagetext = replyTxt.text.trimmingCharacters(in: .whitespacesAndNewlines)
    hhmessages.insert(messagetext as AnyObject, at: hhmessages.endIndex)

    let indexPath = IndexPath(row: hhmessages.count - 1, section: 0)
    tableView.beginUpdates()
    tableView.insertRows(at: [indexPath], with: .automatic)
    tableView.endUpdates()
    tableView.transform = CGAffineTransform(rotationAngle: -(CGFloat)(Double.pi));
    tableView.scrollToRow(at: indexPath, at: .bottom, animated: true)

    replyTxt.text = ""
    textViewDidChange(replyTxt)
    let recipient = messages["username"] as! String
    let rid = String(describing: messages["recipient_id"]!)
    let uuid = messages["uuid"] as! String
    puuid = UUID().uuidString

    // prepare request
    let url = URL(string: "http://localhost/messagepost.php")!
    let body = "sender_id=\(user_id)&sender=\(username)&text=\(messagetext)&recipient_id=\(rid)&recipient=\(recipient)&uuid=\(uuid)&puuid=\(puuid)"

    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    request.httpBody = body.data(using: .utf8)

    // send request
    URLSession.shared.dataTask(with: request)  (data, response, error) in
        DispatchQueue.main.async 

            // error happened
            if error != nil 
                Helper().showAlert(title: "Server Error", message: error!.localizedDescription, in: self)
                return
            

            do 
                // converting received data from the server into json format
                let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSDictionary

                // safe mode of casting json
                guard let parsedJSON = json else 
                    return
                

                // if the status of JSON is 200 - success
                if parsedJSON["status"] as! String == "200" 

                 else 
                    Helper().showAlert(title: "400", message: parsedJSON["status"] as! String, in: self)
                    return
                

                // json error
             catch 
                Helper().showAlert(title: "JSON Error", message: error.localizedDescription, in: self)
                return
            

        
        .resume()




@IBAction func replyBtn_clicked(_ sender: Any) 

    if replyTxt.text.isEmpty == false && replyTxt.text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty == false 
        uploadPost()
        //tableView.reloadData()
    


【问题讨论】:

【参考方案1】:

在添加新消息时,您正在将 String 添加到 hhmessages 数组中

let messagetext = replyTxt.text.trimmingCharacters(in: .whitespacesAndNewlines)
hhmessages.insert(messagetext as AnyObject, at: hhmessages.endIndex)

但在cellForRowAt 方法中,您尝试使用“messagetext”键从hhmessages 数组中获取String

let pictureURL = hhmessages[indexPath.row]["uploadpath"] as? String
let hhpost = hhmessages[indexPath.row]
let text = hhpost["messagetext"] as? String

改变

hhmessages.insert(messagetext as AnyObject, at: hhmessages.endIndex)

hhmessages.insert(["messagetext": messagetext] as AnyObject, at: hhmessages.endIndex)

不要使用 AnyObject 的数组,而是使用结构

var hhmessages = AnyObject

struct Message 
    var uploadpath: URL?
    var messagetext: String?    

var hhmessages = [Message]()

【讨论】:

以上是关于UITextfield 使用插入在 UITableView 中显示空行的主要内容,如果未能解决你的问题,请参考以下文章

处理 UItableView 中 UItextfield 的委托

UITextfield 使用插入在 UITableView 中显示空行

检测对 UITableView 空白区域的点击

如何在用户编辑UITEXTFIELD时自动插入字符串

UITable 视图界面构建器创建

更改 UITextField 和 UITextView 光标/插入符号颜色