sách gpt4 ai đã đi

ios - 现有 CollectionView 图像在滚动时发生变化

In lại 作者:行者123 更新时间:2023-11-30 12:12:16 29 4
mua khóa gpt4 Nike

我已经查看了很多问题,我不相信这是重复使用单元格的结果,因为新的单元格图像是正确的,但是现有的单元格图像不正确并且曾经是正确的。我会先发布图片,以便更容易理解问题。

Before Scrolling

Existing Image Changed on Scroll

nhập mô tả hình ảnh ở đây

我有一个图像单元的 Collection View (类似于 Instagram 的用户页面)。我正在从 Firebase 获取所有数据。我在屏幕初始加载时收到了前 12 个帖子。但是,如果您快速向下滚动,现有单元格图像将更改为新获取的图像。我不确定为什么会发生这种情况......也许这是一个缓存问题?该问题仅在您第一次加载屏幕时出现。我尝试将图像设置为零,如下所示:

override func prepareForReuse() {
super.prepareForReuse()
self.imageView.image = UIImage()
}

但这对解决问题没有帮助。

这是我的 cellForItemAt:

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "imageCell", for: indexPath) as! ImageCell
cell.indexPath = indexPath
cell.imageView.downloadImage(from: currentTablePosts[indexPath.row].pathToImage)
cell.layer.borderWidth = 1
cell.layer.borderColor = UIColor.black.cgColor
return cell
}

图像下载和缓存:

let imageCache = NSCache()

extension UIImageView {

func downloadImage(from imgURL: String!) {
let url = URLRequest(url: URL(string: imgURL)!)

// set initial image to nil so it doesn't use the image from a reused cell
image = nil

// check if the image is already in the cache
if let imageToCache = imageCache.object(forKey: imgURL! as NSString) {
self.image = imageToCache
trở lại
}

// download the image asynchronously
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
if error != nil {
// user an alert to display the error
if let topController = UIApplication.topViewController() {
Helper.showAlertMessage(vc: topController, title: "Error Downloading Image", message: error as! String)
}
trở lại
}

DispatchQueue.main.async {
// create UIImage
let imageToCache = UIImage(data: data!)
// add image to cache
imageCache.setObject(imageToCache!, forKey: imgURL! as NSString)
self.image = imageToCache
}
}
task.resume()
}
}

Firebase 查询:

static func getInitialTablesPosts(tableNumber: String) {
tableReference.child(tableNumber).queryLimited(toLast: 12).observeSingleEvent(of: .value, with: { snap in
for child in snap.children {
let child = child as? DataSnapshot
if let post = child?.value as? [String: AnyObject] {
let posst = Post()
if let author = post["author"] as? String, let likes = post["likes"] as? Int, let pathToImage = post["pathToImage"] as? String, let postID = post["postID"] as? String, let postDescription = post["postDescription"] as? String, let timestamp = post["timestamp"] as? Double, let category = post["category"] as? String, let table = post["group"] as? String, let userID = post["userID"] as? String, let numberOfComments = post["numberOfComments"] as? Int, let region = post["region"] as? String {

posst.author = author
posst.likes = likes
posst.pathToImage = pathToImage
posst.postID = postID
posst.userID = userID
posst.fancyPostDescription = Helper.createAttributedString(author: author, postText: postDescription)
posst.postDescription = author + ": " + postDescription
posst.timestamp = timestamp
posst.table = table
posst.region = region
posst.category = category
posst.numberOfComments = numberOfComments
posst.userWhoPostedLabel = Helper.createAttributedPostLabel(username: author, table: table, region: region, category: category)

if let people = post["peopleWhoLike"] as? [String: AnyObject] {
for(_, person) in people {
posst.peopleWhoLike.append(person as! String)
}
}
currentTablePosts.insert(posst, at: 0)
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "reloadTableCollectionView"), object: nil)
} // end of if let
}
}
})
tableReference.removeAllObservers()
}

static func getMoreTablePosts(tableNumber: String, lastVisibleKey: String) {
print("FIRED...")
let currentNumberOfPosts = currentTablePosts.count
print("Number of posts before fetiching ", currentNumberOfPosts)
print("Oldest post key ", oldestTableKeys[tableNumber] ?? "not set yet", "***********")

tableReference.child(tableNumber).queryOrderedByKey().queryEnding(atValue: lastVisibleKey).queryLimited(toLast: 12).observeSingleEvent(of: .value, with: { snap in

for child in snap.children {
let child = child as? DataSnapshot
if let post = child?.value as? [String: AnyObject] {
if let id = post["postID"] as? String {
if id == lastVisibleKey {
trở lại
}
}
let posst = Post()
if let author = post["author"] as? String, let likes = post["likes"] as? Int, let pathToImage = post["pathToImage"] as? String, let postID = post["postID"] as? String, let postDescription = post["postDescription"] as? String, let timestamp = post["timestamp"] as? Double, let category = post["category"] as? String, let table = post["group"] as? String, let userID = post["userID"] as? String, let numberOfComments = post["numberOfComments"] as? Int, let region = post["region"] as? String {

posst.author = author
posst.likes = likes
posst.pathToImage = pathToImage
posst.postID = postID
posst.userID = userID
posst.fancyPostDescription = Helper.createAttributedString(author: author, postText: postDescription)
posst.postDescription = author + ": " + postDescription
posst.timestamp = timestamp
posst.table = table
posst.region = region
posst.category = category
posst.numberOfComments = numberOfComments
posst.userWhoPostedLabel = Helper.createAttributedPostLabel(username: author, table: table, region: region, category: category)

if let people = post["peopleWhoLike"] as? [String: AnyObject] {
for(_, person) in people {
posst.peopleWhoLike.append(person as! String)
}
}
currentTablePosts.insert(posst, at: currentNumberOfPosts)
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "reloadTableCollectionView"), object: nil)
if let oldestTableKey = oldestTableKeys[tableNumber] {
if postID == oldestTableKey {
print("returning")
print("number of posts on return \(currentTablePosts.count)")
trở lại
}
}
} // end if let
}
}
})
tableReference.removeAllObservers()
}

1 Câu trả lời

* 更新 *

根据我的经验,此处使用的图像缓存仍然存在一些问题。此后我开始使用 Kingfisher这非常容易设置和使用。

* 旧解决方案 *

xuất hiệnsolution基于评论中建议的答案。

我修改了用于缓存图像的扩展程序。虽然将来我想我会子类 UIImageView 。这是我的代码的修改版本。

nhập khẩu UIKit

let userImageCache = NSCache()
let imageCache = NSCache()
var imageURLString: String?


extension UIImageView {

public func imageFromServerURL(urlString: String, collectionView: UICollectionView, indexpath : IndexPath) {
imageURLString = urlString

if let url = URL(string: urlString) {
image = nil
if let imageFromCache = imageCache.object(forKey: urlString as AnyObject) as? UIImage {
self.image = imageFromCache
trở lại
}

URLSession.shared.dataTask(with: url, completionHandler: { (data, response, error) in
if error != nil{
if let topController = UIApplication.topViewController() {
Helper.showAlertMessage(vc: topController, title: "Error Downloading Image", message: error as! String)
}
trở lại
}

DispatchQueue.main.async(execute: {
if let imgaeToCache = UIImage(data: data!){
if imageURLString == urlString {
self.image = imgaeToCache
}
imageCache.setObject(imgaeToCache, forKey: urlString as AnyObject)// calls when scrolling
collectionView.reloadItems(at: [indexpath])
}
})
}) .resume()
}
}

func downloadImage(from imgURL: String!) {
let url = URLRequest(url: URL(string: imgURL)!)

// set initial image to nil so it doesn't use the image from a reused cell
image = nil

// check if the image is already in the cache
if let imageToCache = imageCache.object(forKey: imgURL! as AnyObject) as? UIImage {
self.image = imageToCache
trở lại
}

// download the image asynchronously
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
if error != nil {
// user an alert to display the error
if let topController = UIApplication.topViewController() {
Helper.showAlertMessage(vc: topController, title: "Error Downloading Image", message: error as! String)
}
trở lại
}

DispatchQueue.main.async {
let imageToCache = UIImage(data: data!)
imageCache.setObject(imageToCache!, forKey: imgURL! as AnyObject)
self.image = imageToCache
}
}
task.resume()
}

func downloadUserImage(from imgURL: String!) {
let url = URLRequest(url: URL(string: imgURL)!)

// set initial image to nil so it doesn't use the image from a reused cell
image = nil

// check if the image is already in the cache
if let imageToCache = userImageCache.object(forKey: imgURL! as NSString) {
self.image = imageToCache
trở lại
}

// download the image asynchronously
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
if error != nil {
// user an alert to display the error
if let topController = UIApplication.topViewController() {
Helper.showAlertMessage(vc: topController, title: "Error Downloading Image", message: error as! String)
}
trở lại
}

DispatchQueue.main.async {
// create UIImage
let imageToCache = UIImage(data: data!)
// add image to cache
userImageCache.setObject(imageToCache!, forKey: imgURL! as NSString)
self.image = imageToCache
}
}
task.resume()
}
}

我创建了第一个方法来缓存collectionView的图像,其他方法仍然用于tableView。缓存也从 let imageCache = NSCache() 更改为至let imageCache = NSCache()

关于ios - 现有 CollectionView 图像在滚动时发生变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45906274/

29 4 0
行者123
Hồ sơ cá nhân

Tôi là một lập trình viên xuất sắc, rất giỏi!

Nhận phiếu giảm giá Didi Taxi miễn phí
Mã giảm giá Didi Taxi
Giấy chứng nhận ICP Bắc Kinh số 000000
Hợp tác quảng cáo: 1813099741@qq.com 6ren.com