当用户在我的应用程序中滚动 UIViewCollectionCells 列表时出现奇怪的行为(每个单元格中的数据随机变化)
Strange behavior when user scrolls the list of UIViewCollectionCells in my app (the data in each cell changes randomly)
在我的应用程序中,我正在使用 UICollectionView
并且我决定在下面的代码中使用它:
class UserList: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
@IBOutlet weak var tview: UICollectionView!
let reuseIdentifier = "cell"
var items = NSMutableArray()
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = tview.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! MyCollectionViewCell
let user:SingleUser = self.items[indexPath.item] as! SingleUser
cell.username.text = user.name
if let checkedUrl = NSURL(string: user.photo) {
cell.userImg.contentMode = .ScaleAspectFit
getDataFromUrl(checkedUrl) { (data, response, error) in
dispatch_async(dispatch_get_main_queue()) { () -> Void in
guard let data = data where error == nil else { return }
print(response?.suggestedFilename ?? "")
cell.userImg.image = UIImage(data: data)
}
}
}
return cell
}
所以我有一个带有 UILabel
和 UIImage
的单元格,对于从 json 获取的每个 object,我解析它并将用户的数据分配给该单元格。
当我加载 window 时,我看到用户名和他们的照片,但是当我开始滚动查看 collection 时,用户的照片发生变化,用户得到的照片与他们应该拥有的不同。
我读过它可能与单元格重用有关(到目前为止我对此一无所知),我只是假设它应该加载一次(当用户打开此面板时)然后保持原样。但是,每次用户滚动该列表时,该数据似乎都是 "fetched"。
那么我怎样才能准确解决我的问题并确保每次用户滚动列表时数据都是正确的?
还有一件事可能在这里有用 - 从 url 获取照片的方法 getDataFromUrl
:
func getDataFromUrl(url:NSURL, completion: ((data: NSData?, response: NSURLResponse?, error: NSError? ) -> Void)) {
NSURLSession.sharedSession().dataTaskWithURL(url) { (data, response, error) in
completion(data: data, response: response, error: error)
}.resume()
}
Eugene 说的是对的,但如果你不想更改代码,你已经太多了。您可以在 SingleUser 上添加一个可选的 UIImage 属性,将其命名为 "image," 然后您可以这样说:
if user.image == nil{
getDataFromUrl(checkedUrl) { (data, response, error) in
dispatch_async(dispatch_get_main_queue()) { () -> Void in
guard let data = data where error == nil else { return }
print(response?.suggestedFilename ?? "")
let image = UIImage(data: data)
user.image = image
//Check if this cell still has the same indexPath, else it has been dequeued, and image shouldn't be updated
if collectionView.indexPathForCell(cell) == indexPath
{
cell.userImg.image = image
}
}
}
}else{
cell.userImg.image = user.image!
}
}
在我的应用程序中,我正在使用 UICollectionView
并且我决定在下面的代码中使用它:
class UserList: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
@IBOutlet weak var tview: UICollectionView!
let reuseIdentifier = "cell"
var items = NSMutableArray()
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = tview.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! MyCollectionViewCell
let user:SingleUser = self.items[indexPath.item] as! SingleUser
cell.username.text = user.name
if let checkedUrl = NSURL(string: user.photo) {
cell.userImg.contentMode = .ScaleAspectFit
getDataFromUrl(checkedUrl) { (data, response, error) in
dispatch_async(dispatch_get_main_queue()) { () -> Void in
guard let data = data where error == nil else { return }
print(response?.suggestedFilename ?? "")
cell.userImg.image = UIImage(data: data)
}
}
}
return cell
}
所以我有一个带有 UILabel
和 UIImage
的单元格,对于从 json 获取的每个 object,我解析它并将用户的数据分配给该单元格。
当我加载 window 时,我看到用户名和他们的照片,但是当我开始滚动查看 collection 时,用户的照片发生变化,用户得到的照片与他们应该拥有的不同。
我读过它可能与单元格重用有关(到目前为止我对此一无所知),我只是假设它应该加载一次(当用户打开此面板时)然后保持原样。但是,每次用户滚动该列表时,该数据似乎都是 "fetched"。
那么我怎样才能准确解决我的问题并确保每次用户滚动列表时数据都是正确的?
还有一件事可能在这里有用 - 从 url 获取照片的方法 getDataFromUrl
:
func getDataFromUrl(url:NSURL, completion: ((data: NSData?, response: NSURLResponse?, error: NSError? ) -> Void)) {
NSURLSession.sharedSession().dataTaskWithURL(url) { (data, response, error) in
completion(data: data, response: response, error: error)
}.resume()
}
Eugene 说的是对的,但如果你不想更改代码,你已经太多了。您可以在 SingleUser 上添加一个可选的 UIImage 属性,将其命名为 "image," 然后您可以这样说:
if user.image == nil{
getDataFromUrl(checkedUrl) { (data, response, error) in
dispatch_async(dispatch_get_main_queue()) { () -> Void in
guard let data = data where error == nil else { return }
print(response?.suggestedFilename ?? "")
let image = UIImage(data: data)
user.image = image
//Check if this cell still has the same indexPath, else it has been dequeued, and image shouldn't be updated
if collectionView.indexPathForCell(cell) == indexPath
{
cell.userImg.image = image
}
}
}
}else{
cell.userImg.image = user.image!
}
}