techgirl
techgirl

Reputation: 323

UITextfield showing empty row in UITableView using insert

I have a chat feature on my app that updates the table instantly when a user enters new text. Unfortunately when a user enters the text it shows any empty row in the uitableview. When I exit out of the screen and return that new value is now there at the end of the table. So even though it's showing an empty row in the uitableview it's submitting the actual value to the database.

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()
    }

}

Upvotes: 0

Views: 48

Answers (1)

RajeshKumar R
RajeshKumar R

Reputation: 15758

While appending a new message you are adding a String to the hhmessages array

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

But in cellForRowAt method you are trying to get the String from hhmessages array using "messagetext" key

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

Change

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

to

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

Instead of using array of AnyObject, use a struct

var hhmessages = AnyObject

struct Message {
    var uploadpath: URL?
    var messagetext: String?    
}
var hhmessages = [Message]()

Upvotes: 1

Related Questions