tableView 使用 UIImages 渲染缓慢
tableView renders slowly with UIImages
我有一个自定义单元格,用于在应用程序上使用用户 post 填充 tableView。用户可以post发短信或发短信带uiimage
我最初遇到的问题是在包含图像时设置单元格的高度。我最终在 tableview 单元格中得到了高度荒谬的图像,并且图像加载不正确。
所以我将下面的代码添加到 tableView CellforRowAt 函数中,以更改图像的框架,以便以统一的大小加载 UIImage。虽然这现在工作得很好,但当我在 tableview 上滚动时,它超级小故障而且速度很慢。我认为这是因为框架被改变了,处理这个新框架需要一段时间。有没有可能让它更高效更流畅?
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "postCell", for: indexPath) as! PostTableViewCell
cell.set(post: posts[indexPath.row])
cell.delegate = self
cell.commentDelegate = self
cell.likeDelegate = self
cell.selectionStyle = .none
let imageIndex = posts[indexPath.row].mediaURL
let url = NSURL(string: imageIndex)! as URL
if let imageData: NSData = NSData(contentsOf: url) {
let image = UIImage(data: imageData as Data)
let newWidth = cell.MediaPhoto.frame.width
let scale = newWidth/image!.size.width
let newHeight = image!.size.height * scale
UIGraphicsBeginImageContext(CGSize(width: newWidth, height: newHeight))
image!.draw(in: CGRect(x: 0, y: 0, width: newWidth, height: newHeight))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
cell.MediaPhoto.image = newImage
cell.MediaPhoto.contentMode = .scaleToFill
cell.MediaPhoto.clipsToBounds = true
}
}
return cell
}
尝试将工作移到主线程之外。
class PostTableViewCell: UITableViewCell {
var image: UIImage? {
didSet {
setNeedsDisplay()
}
}
func set(post: Post) {
DispatchQueue.global().async { [weak self] in
let strongSelf = self!
if let url = NSURL(string: strongSelf.mediaUrl) as URL?,
let imageData: NSData = NSData(contentsOf: url) {
strongSelf.image = UIImage(data: imageData as Data)
}
}
}
override func draw(_ rect: CGRect) {
guard let image = image else { super.draw(rect) }
let newWidth = MediaPhoto.frame.width
let scale = newWidth/image.size.width
let newHeight = image.size.height * scale
UIGraphicsBeginImageContext(CGSize(width: newWidth, height: newHeight))
image!.draw(in: CGRect(x: 0, y: 0, width: newWidth, height: newHeight))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
MediaPhoto.image = newImage
MediaPhoto.contentMode = .scaleToFill
MediaPhoto.clipsToBounds = true
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "postCell", for: indexPath) as! PostTableViewCell
if indexPath.section == 0 {
cell.set(post: posts[indexPath.row])
cell.delegate = self
cell.commentDelegate = self
cell.likeDelegate = self
cell.selectionStyle = .none
}
return cell
}
我最终使用此代码将图像大小固定为 400 x 400,效果很好。它不再呈现缓慢或故障。
func set(post:Posts) {
self.post = post
// get PROFILE image
let url = post.url
profileImageView.sd_setImage(with: url, completed: nil)
// get MEDIA image
let mediaString = post.urlM.absoluteString
if mediaString == "none" {
MediaPhoto.image = nil
} else {
let mediaUrl = post.urlM
MediaPhoto.sd_setImage(with: mediaUrl, completed: nil)
//RESIZE MEDIA PHOTO
let itemSize:CGSize = CGSize(width: 400, height: 400)
UIGraphicsBeginImageContextWithOptions(itemSize, false, UIScreen.main.scale)
let imageRect : CGRect = CGRect(x: 0, y: 0, width: itemSize.width, height: itemSize.height)
MediaPhoto!.image?.draw(in: imageRect)
MediaPhoto!.image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
}
}
我有一个自定义单元格,用于在应用程序上使用用户 post 填充 tableView。用户可以post发短信或发短信带uiimage
我最初遇到的问题是在包含图像时设置单元格的高度。我最终在 tableview 单元格中得到了高度荒谬的图像,并且图像加载不正确。
所以我将下面的代码添加到 tableView CellforRowAt 函数中,以更改图像的框架,以便以统一的大小加载 UIImage。虽然这现在工作得很好,但当我在 tableview 上滚动时,它超级小故障而且速度很慢。我认为这是因为框架被改变了,处理这个新框架需要一段时间。有没有可能让它更高效更流畅?
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "postCell", for: indexPath) as! PostTableViewCell
cell.set(post: posts[indexPath.row])
cell.delegate = self
cell.commentDelegate = self
cell.likeDelegate = self
cell.selectionStyle = .none
let imageIndex = posts[indexPath.row].mediaURL
let url = NSURL(string: imageIndex)! as URL
if let imageData: NSData = NSData(contentsOf: url) {
let image = UIImage(data: imageData as Data)
let newWidth = cell.MediaPhoto.frame.width
let scale = newWidth/image!.size.width
let newHeight = image!.size.height * scale
UIGraphicsBeginImageContext(CGSize(width: newWidth, height: newHeight))
image!.draw(in: CGRect(x: 0, y: 0, width: newWidth, height: newHeight))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
cell.MediaPhoto.image = newImage
cell.MediaPhoto.contentMode = .scaleToFill
cell.MediaPhoto.clipsToBounds = true
}
}
return cell
}
尝试将工作移到主线程之外。
class PostTableViewCell: UITableViewCell {
var image: UIImage? {
didSet {
setNeedsDisplay()
}
}
func set(post: Post) {
DispatchQueue.global().async { [weak self] in
let strongSelf = self!
if let url = NSURL(string: strongSelf.mediaUrl) as URL?,
let imageData: NSData = NSData(contentsOf: url) {
strongSelf.image = UIImage(data: imageData as Data)
}
}
}
override func draw(_ rect: CGRect) {
guard let image = image else { super.draw(rect) }
let newWidth = MediaPhoto.frame.width
let scale = newWidth/image.size.width
let newHeight = image.size.height * scale
UIGraphicsBeginImageContext(CGSize(width: newWidth, height: newHeight))
image!.draw(in: CGRect(x: 0, y: 0, width: newWidth, height: newHeight))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
MediaPhoto.image = newImage
MediaPhoto.contentMode = .scaleToFill
MediaPhoto.clipsToBounds = true
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "postCell", for: indexPath) as! PostTableViewCell
if indexPath.section == 0 {
cell.set(post: posts[indexPath.row])
cell.delegate = self
cell.commentDelegate = self
cell.likeDelegate = self
cell.selectionStyle = .none
}
return cell
}
我最终使用此代码将图像大小固定为 400 x 400,效果很好。它不再呈现缓慢或故障。
func set(post:Posts) {
self.post = post
// get PROFILE image
let url = post.url
profileImageView.sd_setImage(with: url, completed: nil)
// get MEDIA image
let mediaString = post.urlM.absoluteString
if mediaString == "none" {
MediaPhoto.image = nil
} else {
let mediaUrl = post.urlM
MediaPhoto.sd_setImage(with: mediaUrl, completed: nil)
//RESIZE MEDIA PHOTO
let itemSize:CGSize = CGSize(width: 400, height: 400)
UIGraphicsBeginImageContextWithOptions(itemSize, false, UIScreen.main.scale)
let imageRect : CGRect = CGRect(x: 0, y: 0, width: itemSize.width, height: itemSize.height)
MediaPhoto!.image?.draw(in: imageRect)
MediaPhoto!.image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
}
}