使用 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
tableView.deleteRows(at:with:) 每次都崩溃
lc 862. Shortest Subarray with Sum at Least K
什么 tableView.reloadRows(at: [indexPath], with: .none) 会像这样崩溃?