使用 InsertRows(at: with) 将 UIImage 插入表中

Posted

技术标签:

【中文标题】使用 InsertRows(at: with) 将 UIImage 插入表中【英文标题】:Insert UIImage into table using InsertRows(at: with) 【发布时间】:2019-12-14 04:06:55 【问题描述】:

我有一个类似于 instagram 和其他人的直接消息传递应用程序。当前,当用户输入文本时,它会立即更新 UI。当用户尝试发送图像时,我遇到了麻烦。它在后端工作,我看到服务器上的图像和数据库中的引用,但它没有用图像更新 UI。相反,它显示一个空行,就好像输入了文本一样。我的代码包含在下面。

上传图片功能

func uploadImage(from imageView: UIImageView) 

    // save method of accessing ID of current user
    guard let id = user?["id"], let uuid = messages["uuid"] else 
        return
    
    let recipient = messages["username"] as! String
    let rid = String(describing: messages["sender_id"]!)
    let sender = user!["username"] as! String
    puuid = UUID().uuidString

    // STEP 1. Declare URL, Request and Params
    // url we gonna access (API)
    let url = URL(string: "https://localhost/messagepost.php")!

    // declaring reqeust with further configs
    var request = URLRequest(url: url)

    // POST - safest method of passing data to the server
    request.httpMethod = "POST"

    // values to be sent to the server under keys (e.g. ID, TYPE)
    let params = ["sender_id": id, "uuid": uuid, "sender": sender, "recipient_id": rid, "recipient": recipient, "puuid": puuid]

    // MIME Boundary, Header
    let boundary = "Boundary-\(NSUUID().uuidString)"
    request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
    let param = ["puuid" : puuid]

    // if in the imageView is placeholder - send no picture to the server
    // Compressing image and converting image to 'Data' type
    var imageData = Data()

    if pictureImg.image != nil 
        imageData = pictureImg.image!.jpegData(compressionQuality: 0.5)!
    

    // assigning full body to the request to be sent to the server
    request.httpBody = Helper().body(with: params, filename: "\(param).jpg", filePathKey: "file", imageDataKey: imageData, boundary: boundary) as Data

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

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


            do 

                // save mode of casting any data
                guard let data = data else 
                    Helper().showAlert(title: "Data Error", message: error!.localizedDescription, in: self)
                    return
                

                // fetching JSON generated by the server - php file
                let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? NSDictionary

                // save method of accessing json constant
                guard let parsedJSON = json else 
                    return
                

                // uploaded successfully
                if parsedJSON["status"] as! String == "200" 

                 else 

                    // show the error message in AlertView
                    if parsedJSON["message"] != nil 
                        let message = parsedJSON["message"] as! String
                        Helper().showAlert(title: "Error", message: message, in: self)
                    

                

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

        
    .resume()

    hhmessages.insert([pictureImg.image: imageData] 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.scrollToRow(at: indexPath, at: .bottom, animated: true)

上传文字功能

func uploadPost() 
    // validating vars before sending to the server
    guard let user_id = user?["id"] as? String, let sender = user!["username"] as? String, let avaPath = user?["ava"] as? String
        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
                let ava = currentUser_ava
            

            return
    

    let messagetext = replyTxt.text!.trimmingCharacters(in: .whitespacesAndNewlines)
    let avame = user!["ava"]
    let postimage = pictureImg.image

    let recipientfe = messages["recipient"]
    let uuidfe = messages["uuid"] as! String

    hhmessages.insert(["messagetext": messagetext] as AnyObject, at: hhmessages.endIndex)
    print(user?["ava"])

    let indexPath = IndexPath(row: hhmessages.count - 1, section: 0)

    tableView.beginUpdates()
    tableView.insertRows(at: [indexPath], with: .automatic)

    tableView.endUpdates()

    tableView.scrollToRow(at: indexPath, at: .bottom, animated: true)

    replyTxt.text = ""

    let recipient = messages["username"] as! String

    let rid = String(describing: messages["sender_id"]!)
    let uuid = messages["uuid"] as! String

    puuid = UUID().uuidString


    // prepare request
    let url = URL(string: "https://localhost/messagepost.php")!
    let body = "sender_id=\(user_id)&sender=\(sender)&text=\(messagetext)&recipient_id=\(rid)&recipient=\(recipient)&uuid=\(uuidfe)&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" 

                        // comment is inserted
                        print(parsedJSON)

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

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

            
        .resume()

    

表格查看代码

 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
return hhmessages.count 

func numberOfSections(in tableView: UITableView) -> Int 
return 1
 

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
if pictureURL?.isEmpty == true 
    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! ConversationCell
    cell.transform = CGAffineTransform(rotationAngle: CGFloat(Double.pi));

    isLoading = true

    let hhpost = hhmessages[indexPath.row]
    let smimages = hhpost["path"] as? UIImage
    let text = hhmessages[indexPath.row]["messagetext"] as! String
    cell.messageLbl.text = text
    cell.smavaImg.image = smimages

        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
          // get main queue to this block of code to communicate back
   DispatchQueue.main.async 
    cell.messageLbl.sizeToFit()
    tableView.transform = CGAffineTransform(rotationAngle: -CGFloat.pi)
    cell.transform = CGAffineTransform(rotationAngle: CGFloat.pi)


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

    cell.smavaImg.image = smimages
    //if let message = messageData 
    for i in 0 ..< self.incoming.count 
        // Confiture the constraints for cell
        if self.incoming[indexPath.row] == 1 
                             // Constraints
           cell.lefBubbleConstraint.isActive = true
            cell.rightBubbleConstraint.isActive = false
            if cell.postpictureImg.image == nil 
                cell.postpictureImg.backgroundColor = colorwhite
                cell.postpictureImg.clipsToBounds = true

            
            else 
                cell.postpictureImg.backgroundColor = .clear
                cell.postpictureImg.clipsToBounds = true

            

        
        else if self.incoming[indexPath.row] == 0 


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

            
            else 
                cell.postpictureImg.backgroundColor = .clear
                cell.postpictureImg.clipsToBounds = true

            

        

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




【问题讨论】:

【参考方案1】:

我注意到您在 cellForRowAt 数据源函数中获得了单元格的图像。您将其作为“上传路径”键的值。虽然您在插入图像时不使用该键。

因此,pictureURL?.isEmpty == true 在此将始终为 true 案例。

我建议您使用相同的键来插入图像。类似:

hhmessages.insert(["uploadpath": pictureImg.image] as AnyObject, at: hhmessages.endIndex)

然后当你在 cellForRowAt 中得到它时。您需要检查类型:

if pictureURL.isEmpty 
    //text
 else 
    //image
    if pictureURL is UIImage 
       //uiimage
     else 
       //url
    

【讨论】:

谢谢@hasan 我对条件语句的修改有点困惑。图像将始终上传一个 URL。你建议应该去那里? 我使用 "uploadpath": pictureImg.image 进行了尝试,但它仍然没有使用图像更新 UI。还有其他想法吗?我非常感谢您的帮助。 您正在上传图像,然后您想将其插入到您的 tableview 中,而无需再次从服务器获取数据。因此,当您完成上传时,您没有该上传图片的网址。所以你实际上将图像本身插入到 hhmessage 中。反正你没有网址。所以不,它并不总是你的 hhmessage 中的网址 没有其他想法。这就是你的问题的想法。 hhmessages.insert([pictureImg.image: imageData] as AnyObject, at: hhmessages.endIndex) 这一行你以一种奇怪的方式插入图像。我建议这样做:[“uploadpath”:pictureImg.image]。这样您就可以稍后在 cellForRowAt 中使用密钥获取它。

以上是关于使用 InsertRows(at: with) 将 UIImage 插入表中的主要内容,如果未能解决你的问题,请参考以下文章

swift tableview 将 reloadData 更改为 insertRows

如何通过平滑滚动将最后一行添加到 UITableView?

等待 UITableView 完成插入

tableView.deleteRows(at:with:) 每次都崩溃

lc 862. Shortest Subarray with Sum at Least K

什么 tableView.reloadRows(at: [indexPath], with: .none) 会像这样崩溃?