Swift UITableView 中的异步调用
Swift Async Call in UITableView
异步调用 将 UIImage 作为 tableView 中的 NSTextAttachment 加载到 textView 的最佳方法是什么?到目前为止,这是非常糟糕的。
我正在使用 URL 字符串在多个 tableView 单元格中加载单个图像。
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell")
//Transform Data From ^ to load at the bottom
tableView.transform = CGAffineTransform (scaleX: 1,y: -1);
cell?.contentView.transform = CGAffineTransform (scaleX: 1,y: -1);
cell?.accessoryView?.transform = CGAffineTransform (scaleX: 1,y: -1);
let username = cell?.viewWithTag(1) as! UITextView
username.text = messageArray[indexPath.row].username
let message = cell?.viewWithTag(2) as! UITextView
//message.text = messageArray[indexPath.row].message // delete later
var test = messageArray[indexPath.row].uploadedPhotoUrl
print(test ?? String.self)
if(test != ""){
// create an NSMutableAttributedString that we'll append everything to
let fullString = NSMutableAttributedString(string: "")
// create our NSTextAttachment
let image1Attachment = NSTextAttachment()
URLSession.shared.dataTask(with: NSURL(string: messageArray[indexPath.row].uploadedPhotoUrl)! as URL, completionHandler: { (data, response, error) -> Void in
if error != nil {
print(error ?? String())
return
}
DispatchQueue.main.async(execute: { () -> Void in
let image = UIImage(data: data!)
image1Attachment.image = image
//calculate new size. (-20 because I want to have a litle space on the right of picture)
let newImageWidth = (message.bounds.size.width - 20 )
//resize this
image1Attachment.bounds = CGRect.init(x: 0, y: 0, width: newImageWidth, height: 200)
// wrap the attachment in its own attributed string so we can append it
let image1String = NSAttributedString(attachment: image1Attachment)
// add the NSTextAttachment wrapper to our full string, then add some more text.
fullString.append(image1String)
fullString.append(NSAttributedString(string: message.text))
// draw the result in a label
message.attributedText = fullString
//message.textStorage.insert(image1String, at: message.selectedRange.location)
message.textColor = .white
test = ""
})
}).resume()
}else {
message.text = messageArray[indexPath.row].message
}
let timeStamp = cell?.viewWithTag(3) as! UILabel
timeStamp.text = messageArray[indexPath.row].timeStamp
let imageView = cell?.viewWithTag(4) as! UIImageView
imageView.image = nil
let urlString = messageArray[indexPath.row].photoUrl
imageView.layer.cornerRadius = 10
imageView.clipsToBounds = true
//Load profile image(on cell) with URL & Alamofire Library
let downloadURL = NSURL(string: urlString!)
imageView.af_setImage(withURL: downloadURL! as URL)
return cell!
}
当索引滚动(出现和消失)时图像仍然滞后,也没有完全加载
您在 tableviewcell 滚动时一次加载图像。有一些时间调用服务,然后等待返回响应,因此虽然在另一个线程上,但会影响滚动。
您可以尝试一次分批调用 10 或 20 个图像。
TL/DR:
学习编写更好的代码。
对于初学者来说,tableView(:cellForRowAt:)
不可能在 16 毫秒内完成所有工作。我认为您应该为初学者重新考虑您的应用程序结构和架构。将网络调用抽象为可以在后台线程上 运行 的 API 会更好地为您的应用程序服务。
一种方法是将许多实现抽象化为OperationQueue
Ray Wenderlich 有几个教程介绍了它的工作原理。这个特别的是为 Swift 1.2 编写的,但是 Operation
的原则在那里。
异步调用 将 UIImage 作为 tableView 中的 NSTextAttachment 加载到 textView 的最佳方法是什么?到目前为止,这是非常糟糕的。
我正在使用 URL 字符串在多个 tableView 单元格中加载单个图像。
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell")
//Transform Data From ^ to load at the bottom
tableView.transform = CGAffineTransform (scaleX: 1,y: -1);
cell?.contentView.transform = CGAffineTransform (scaleX: 1,y: -1);
cell?.accessoryView?.transform = CGAffineTransform (scaleX: 1,y: -1);
let username = cell?.viewWithTag(1) as! UITextView
username.text = messageArray[indexPath.row].username
let message = cell?.viewWithTag(2) as! UITextView
//message.text = messageArray[indexPath.row].message // delete later
var test = messageArray[indexPath.row].uploadedPhotoUrl
print(test ?? String.self)
if(test != ""){
// create an NSMutableAttributedString that we'll append everything to
let fullString = NSMutableAttributedString(string: "")
// create our NSTextAttachment
let image1Attachment = NSTextAttachment()
URLSession.shared.dataTask(with: NSURL(string: messageArray[indexPath.row].uploadedPhotoUrl)! as URL, completionHandler: { (data, response, error) -> Void in
if error != nil {
print(error ?? String())
return
}
DispatchQueue.main.async(execute: { () -> Void in
let image = UIImage(data: data!)
image1Attachment.image = image
//calculate new size. (-20 because I want to have a litle space on the right of picture)
let newImageWidth = (message.bounds.size.width - 20 )
//resize this
image1Attachment.bounds = CGRect.init(x: 0, y: 0, width: newImageWidth, height: 200)
// wrap the attachment in its own attributed string so we can append it
let image1String = NSAttributedString(attachment: image1Attachment)
// add the NSTextAttachment wrapper to our full string, then add some more text.
fullString.append(image1String)
fullString.append(NSAttributedString(string: message.text))
// draw the result in a label
message.attributedText = fullString
//message.textStorage.insert(image1String, at: message.selectedRange.location)
message.textColor = .white
test = ""
})
}).resume()
}else {
message.text = messageArray[indexPath.row].message
}
let timeStamp = cell?.viewWithTag(3) as! UILabel
timeStamp.text = messageArray[indexPath.row].timeStamp
let imageView = cell?.viewWithTag(4) as! UIImageView
imageView.image = nil
let urlString = messageArray[indexPath.row].photoUrl
imageView.layer.cornerRadius = 10
imageView.clipsToBounds = true
//Load profile image(on cell) with URL & Alamofire Library
let downloadURL = NSURL(string: urlString!)
imageView.af_setImage(withURL: downloadURL! as URL)
return cell!
}
当索引滚动(出现和消失)时图像仍然滞后,也没有完全加载
您在 tableviewcell 滚动时一次加载图像。有一些时间调用服务,然后等待返回响应,因此虽然在另一个线程上,但会影响滚动。
您可以尝试一次分批调用 10 或 20 个图像。
TL/DR: 学习编写更好的代码。
对于初学者来说,tableView(:cellForRowAt:)
不可能在 16 毫秒内完成所有工作。我认为您应该为初学者重新考虑您的应用程序结构和架构。将网络调用抽象为可以在后台线程上 运行 的 API 会更好地为您的应用程序服务。
一种方法是将许多实现抽象化为OperationQueue
Ray Wenderlich 有几个教程介绍了它的工作原理。这个特别的是为 Swift 1.2 编写的,但是 Operation
的原则在那里。