输入新值时复制表的最后一行 [英] Duplicating last row of table when new value entered

查看:50
本文介绍了输入新值时复制表的最后一行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的应用程序中具有聊天功能。该页面将现有数据作为名为hhmessages的数组加载。对话中的最后一条消息是欢迎,当我输入新文本谢谢并按Enter时,表格会自动再次显示欢迎而不是谢谢。如果它退出页面并立即返回显示谢谢作为最后一条消息。它在后端工作,只是当输入时即时更新未在UITableView中显示值。

I have a chat feature within my app. The page loads the existing data as an array called hhmessages. The last message in the conversation was 'Welcome', when I enter new text 'Thank You' and hit enter the table automatically displays 'Welcome' again instead of 'Thank You.' If it exit out of the page and come back it now shows 'Thank You' as the last message. It's working on the backend just the instant update isn't showing the value in the UITableView when entered.

这是针对iPhone应用程序的。
已更新为显示完整代码-现在已删除反向条目,新条目显示为空白。

This is for an iPhone app. UPDATED TO SHOW COMPLETE CODE - Now that reverse has been removed the new entry shows as blank.

import UIKit
import Foundation

 extension String {

    // Calculeta the hight string Function
    func calculateTextFrameRect(
        objectsInPlaceHeight: CGFloat,
        objectsInPlaceWidth: CGFloat,
        fontSize: CGFloat,
        fontWeight: CGFloat) -> CGSize
    {
        let bounding = CGSize(width: UIScreen.main.bounds.width - objectsInPlaceWidth, height: .infinity)
        let rect = NSString(string: self).boundingRect(
            with: bounding,
            options: NSStringDrawingOptions.usesFontLeading.union(NSStringDrawingOptions.usesLineFragmentOrigin),
            attributes: [NSAttributedStringKey.font: UIFont.systemFont(ofSize: fontSize, weight: UIFont.Weight(rawValue: fontWeight))],
            context: nil)
        return CGSize(width: UIScreen.main.bounds.width, height: rect.height + objectsInPlaceHeight )
    }
}
// Messages for test
let frame = CGRect(origin: .zero, size: CGSize.init(width: 375, height: 559))

class Message {
    let message: String
    var incoming: [Int]
    let image: UIImage
    var avas = UIImage()
    init(message: String, image: UIImage, incoming: Int, avas: UIImage) {
        self.message = message
        self.image = image
        self.incoming = [incoming]
        self.avas = avas
    }
}

class ConversationViewController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate, UITableViewDelegate, UITableViewDataSource, UITextViewDelegate {
    //var user = NSDictionary()
    var messages = NSDictionary()
    //var guest = NSDictionary()

    @IBOutlet var senderLbl: UILabel!
    @IBOutlet var senderageLbl: UILabel!
    @IBOutlet var senderraceLbl: UILabel!
    @IBOutlet var sendergenderLbl: UILabel!
    @IBOutlet var sendercityLbl: UILabel!
    @IBOutlet var senderstateLbl: UILabel!
    // @IBOutlet var tableView: UITableView!
    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]()


    //var isSent: String = ""
    var isPictureSelected = false
    //var currentUser_ava = [Any]()
    @IBOutlet var pictureImg: UIImageView!
    @IBOutlet var avaImg: UIImageView!

    @IBOutlet var viewprofile_btn: UIButton!
    @IBOutlet var imgprofile_btn: UIButton!

    @IBOutlet var replyTxt: UITextView!

    //var replyTxt:UITextView!
    @IBOutlet var replyTxt_height: NSLayoutConstraint!

    @IBOutlet var replyTxt_bottom: NSLayoutConstraint!

    @IBOutlet var picSelect: UIButton!
    @IBOutlet var replyBtn: UIButton!
    var puuid = String()
    var imageSelected = false
    var coolIndicator: UIActivityIndicatorView!
    var commentsTextView_bottom_identity = CGFloat()


    @IBOutlet var tableView: UITableView!

    // Table View here + basic configuration

    override func viewDidLoad() {
        //self.tabBarController?.tabBar.isHidden = true

        super.viewDidLoad()
        tableView.transform = CGAffineTransform(rotationAngle: -(CGFloat)(Double.pi));

        // 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

    }
    // pre last func
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)

        // remove observers of notification when the viewController is left
        NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillShow, object: nil)
           NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil)

    }


    // exec-d once notification is caught -> KeyboardWillShow
    @objc func keyboardWillShow(_ notification: Notification) {

        // getting the size of the keyboard
        if let keyboard_size = (notification.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {

            // increasing the bottom constraint by the keyboard's height
            replyTxt_bottom.constant += keyboard_size.height

        }

        // updating the layout with animation
        UIView.animate(withDuration: 0.3) {
            self.view.layoutIfNeeded()
        }

    }


    // exec-d once notification is caught -> KeyboardWillHide
    @objc func keyboardWillHide() {


        // updating the layout with animation
        UIView.animate(withDuration: 0.3) {
            self.view.layoutIfNeeded()
        }

    }
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        //replyTxt().resignFirstResponder()
        self.view.endEditing(false)

    }

    // 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

        print("test 1", pictureURL)

        // no picture in the post
        if pictureURL == nil || pictureURL == "" {
            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
                cell.messageLbl.textAlignment = .right
                cell.messageLbl.backgroundColor = colorSmoothGray
                cell.messageLbl.textColor = .black
                cell.messageLbl.font = UIFont.preferredFont(forTextStyle: UIFontTextStyle.body)
                cell.messageLbl.font?.withSize(25)
                cell.messageLbl.clipsToBounds = true
           cell.messageLbl.sizeToFit()
            pictures.append(UIImage())


            return cell
        } else {
            let cell = tableView.dequeueReusableCell(withIdentifier: "PicCell", for: indexPath) as! PicConversationCell
            cell.transform = CGAffineTransform(rotationAngle: CGFloat(Double.pi))

            let smimages = hhmessages[indexPath.row]["path"] as? UIImage

            cell.smavaImg.image = smimages

            for i in 0 ..< self.incoming.count {
                // Confiture the constraints for cell
                if self.incoming[indexPath.row] == 1 {
                    // Text
                   cell.messageLbl.textAlignment = .left
                    cell.messageLbl.backgroundColor = colorBrandBlue
                    cell.messageLbl.textColor = .white
                    cell.messageLbl.font = UIFont.preferredFont(forTextStyle: UIFontTextStyle.body)
                    cell.messageLbl.font?.withSize(25)
                    cell.messageLbl.clipsToBounds = true

                    // Constraints
                   cell.lefBubbleConstraint.isActive = true
                    cell.rightBubbleConstraint.isActive = false
                    if cell.postpictureImg.image == nil {
                        cell.postpictureImg.backgroundColor = .black
                        cell.postpictureImg.clipsToBounds = true

                    }
                    else {
                        cell.postpictureImg.backgroundColor = .black
                        cell.postpictureImg.clipsToBounds = true

                    }

                }
                else if self.incoming[indexPath.row] == 0 {
                    // Text
                    cell.messageLbl.textAlignment = .right
                    cell.messageLbl.backgroundColor = colorSmoothGray
                    cell.messageLbl.textColor = .black
                    cell.messageLbl.font = UIFont.preferredFont(forTextStyle: UIFontTextStyle.body)
                    cell.messageLbl.font?.withSize(25)
                    cell.messageLbl.clipsToBounds = true

                    // Constraints
                    cell.lefBubbleConstraint.isActive = false
                    cell.rightBubbleConstraint.isActive = true
                    if cell.postpictureImg.image == nil {
                        cell.postpictureImg.backgroundColor = .black
                        cell.postpictureImg.clipsToBounds = true

                    }
                    else {
                        cell.postpictureImg.backgroundColor = .black
                        cell.postpictureImg.clipsToBounds = true

                    }

                }

           if cell.lefBubbleConstraint.isActive == true {


            cell.lefImageConstraint.isActive = true
                cell.rightImageConstraint.isActive = false

            } else {



                cell.lefImageConstraint.isActive = false
                cell.rightImageConstraint.isActive = true
            }


                let pictureString = hhmessages[indexPath.row]["uploadpath"] as! String
                let pictureURL = URL(string: pictureString)!

                // if there are still pictures to be loaded
                if hhmessages.count != pictures.count {

                    URLSession(configuration: .default).dataTask(with: pictureURL) { (data, response, error) in


                        // downloaded
                        if let image = UIImage(data: data!) {

                            self.pictures.append(image)

                            DispatchQueue.main.async {
                                cell.postpictureImg.image = image
                            }
                        }

                        }.resume()

                    // cached picture
                } else {

                    DispatchQueue.main.async {
                        cell.postpictureImg.image = self.pictures[indexPath.row]
                    }
                }


            }
            return cell

        }

    }



    // pre load func
    override func viewDidAppear(_ animated: Bool) {


    }
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)


    }

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

    }

        @IBAction func viewprofile_clicked(_ sender: Any) {
        // performSegue(withIdentifier: "guest2", sender: self.guest)

    }
    @IBAction func imgprofile_clicked(_ sender: Any) {
        // performSegue(withIdentifier: "guest2", sender: self.guest)

    }
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "guest" {

            if let destination = segue.destination as? GuestViewController {
                destination.guest = messages
            }
        }
    }

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

    }
    // exec-d whenever delegated textView has been changed by chars
    func textViewDidChange(_ textView: UITextView) {

        // declaring new size of the textView. we increase the height
        let new_size = textView.sizeThatFits(CGSize.init(width: textView.frame.width, height: CGFloat(MAXFLOAT)))

        // assign new size to the textView
        textView.frame.size = CGSize.init(width: CGFloat(fmaxf(Float(new_size.width), Float(textView.frame.width))), height: new_size.height)

        //UIView.animate(withDuration: 0.2) {
        self.view.layoutIfNeeded()
        //}

    }

    @IBAction func picSelect_clicked(_ sender: AnyObject) {
        // calling picker for selecting iamge
       showActionSheet()
    }
    // this function launches Action Sheet for the photos
    func showActionSheet() {

        // declaring action sheet
        let sheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)

        // declaring camera button
        let camera = UIAlertAction(title: "Camera", style: .default) { (action) in

            // if camera available on device, than show
            if UIImagePickerController.isSourceTypeAvailable(.camera) {
                self.showPicker(with: .camera)
            }

        }

        // declaring library button
        let library = UIAlertAction(title: "Photo Library", style: .default) { (action) in

            // checking availability of photo library
            if UIImagePickerController.isSourceTypeAvailable(.photoLibrary) {
                self.showPicker(with: .photoLibrary)
            }

        }

        // declaring cancel button
        let cancel = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)

        // adding buttons to the sheet
        sheet.addAction(camera)
        sheet.addAction(library)
        sheet.addAction(cancel)

        // present action sheet to the user finally
        self.present(sheet, animated: true, completion: nil)

    }


    // takes us to the PickerController (Controller that allows us to select picture)
    func showPicker(with source: UIImagePickerControllerSourceType) {

        let picker = UIImagePickerController()
        picker.delegate = self
        picker.allowsEditing = true
        picker.sourceType = source
        present(picker, animated: true, completion: nil)

    }


    // executed whenever the image has been picked via pickerController
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {

        // accessing selected image
        let image = info[UIImagePickerControllerEditedImage] as? UIImage

        // assigning selected image to pictureImageView
        pictureImg.image = image

        // cast boolean as TRUE -> Picture Is Selected
        isPictureSelected = true

        // remove pickerController

        pictureImg.image = info[UIImagePickerControllerEditedImage] as? UIImage
        self.dismiss(animated: true, completion: nil)

        // cast as a true to save image file in server
        if pictureImg.image == info[UIImagePickerControllerEditedImage] as? UIImage {
            imageSelected = true
        }
        dismiss(animated: true, completion: nil)
    }


    // exec when pictureImageView has been tapped
    @IBAction func pictureImageView_tapped(_ sender: Any) {

        // declaring action sheet
        let sheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)

        // declaring delete button
        let delete = UIAlertAction(title: "Delete", style: .destructive) { (action) in
            self.pictureImg.image = UIImage()
        }

        // declaring cancel button
        let cancel = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)

        // adding buttons to the sheet
        sheet.addAction(delete)
        sheet.addAction(cancel)

        // present action sheet to the user finally
        self.present(sheet, animated: true, completion: nil)

    }


    // custom body of HTTP request to upload image file
    func createBodyWithParams(_ parameters: [String: String]?, filePathKey: String?, imageDataKey: Data, boundary: String) -> Data {

        let body = NSMutableData();

        if parameters != nil {
            for (key, value) in parameters! {
                body.appendString("--\(boundary)\r\n")
                body.appendString("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
                body.appendString("\(value)\r\n")
            }
        }


        // if file is not selected, it will not upload a file to server, because we did not declare a name file
        var filename = ""

        if imageSelected == true {
            filename = "notes-\(puuid).jpg"
        }


        let mimetype = "image/jpg"

        body.appendString("--\(boundary)\r\n")
        body.appendString("Content-Disposition: form-data; name=\"\(filePathKey!)\"; filename=\"\(filename)\"\r\n")
        body.appendString("Content-Type: \(mimetype)\r\n\r\n")
        body.append(imageDataKey)
        body.appendString("\r\n")

        body.appendString("--\(boundary)--\r\n")

        return body as Data

    }



    @IBAction func replyBtn_clicked(_ sender: Any) {

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

    }



    @objc func keyboardWillChange(notification: NSNotification) {

        let duration = notification.userInfo![UIKeyboardAnimationDurationUserInfoKey] as! Double
        let curve = notification.userInfo![UIKeyboardAnimationCurveUserInfoKey] as! UInt
        let curFrame = (notification.userInfo![UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue
        let targetFrame = (notification.userInfo![UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
        let deltaY = targetFrame.origin.y - curFrame.origin.y
        //print("deltaY",deltaY)

        UIView.animateKeyframes(withDuration: duration, delay: 0.0, options: UIViewKeyframeAnimationOptions(rawValue: curve), animations: {
            self.replyTxt.frame.origin.y+=deltaY // Here You Can Change UIView To UITextField
            self.tableView.frame.origin.y+=deltaY // Here You Can Change UIView To UITextField
            self.replyBtn.frame.origin.y+=deltaY // Here You Can Change UIView To UITextField
            self.picSelect.frame.origin.y+=deltaY // Here You Can Change UIView To UITextField

        },completion: nil)
    }

    func textFieldShouldReturn(_ replyTxt: UITextField) -> Bool {
        replyTxt.resignFirstResponder()
        return true
    }

}


推荐答案

问题是您要在

let indexPath = IndexPath(行:hhmessages.count-1,区域:0)

这是数组的最后一个字段。
但在您的cellForRow中:您有

which is the last field of the array. but in your cellForRow: you have

let text = hhmessages.reversed()[indexPath.row] [ messagetext]如!字符串

它在tableView的最后一个单元格中显示数组的第一个字段。

which shows the first field of your array in the last cell of tableView.

我认为那是您的问题。

I think thats your problem.

这篇关于输入新值时复制表的最后一行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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