UICollectionView reloadData() 不会更新集合视图中的单元格
Posted
技术标签:
【中文标题】UICollectionView reloadData() 不会更新集合视图中的单元格【英文标题】:UICollectionView reloadData() does not update cells in the collection view 【发布时间】:2017-02-15 05:50:18 【问题描述】:这是我想要实现的目标的高级描述; 1. 获取数据 2. 将获取的数据保存在数组对象中 3. 用数组的大小更新collection view
这是我的代码
class ItemcollectionViewController:UICollectionViewController, UICollectionViewDelegateFlowLayout
let cellId = "CellId"
var categories = [Category]()
let viewOptionVar:ViewOptionBar =
let vOV = ViewOptionBar()
vOV.translatesAutoresizingMaskIntoConstraints = false
return vOV
()
private func fetchData()
let categoryController = CategoryController()
categoryController.getAllCategory(username: "blah", password: "password") (returnedCategories, error) -> Void in
if error != nil
print(error)
return
self.categories = returnedCategories!
print("size of the array is \(self.categories.count)")
OperationQueue.main.addOperationself.collectionView?.reloadData()
override func viewDidLoad()
super.viewDidLoad()
fetchData()
collectionView?.backgroundColor = UIColor.white
collectionView?.register(ItemCell.self, forCellWithReuseIdentifier: cellId)
collectionView?.contentInset = UIEdgeInsetsMake(50, 0, self.view.frame.height, self.view.frame.width)
collectionView?.scrollIndicatorInsets = UIEdgeInsetsMake(50, 0, 0, self.view.frame.width)
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
print("in the method \(self.categories.count)")
return self.categories.count
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! ItemCell
cell.category = categories[indexPath.item]
return cell
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
return CGSize(width: 111, height: 111)
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat
return 0
private func setupViweOptionBar()
view.addSubview(viewOptionVar)
view.addConstraintsWithFormat(format: "H:|[v0]|", views: viewOptionVar)
view.addConstraintsWithFormat(format: "V:|[v0(50)]", views: viewOptionVar)
在日志中我可以看到以下语句:
在方法0中
数组大小为3
在我的视野中看不到任何单元格。
谁能告诉我我做错了什么? 提前致谢。
编辑 1 现在我在注册自定义单元格后获取数据。但是还是不行
更新代码:
class ItemcollectionViewController:UICollectionViewController, UICollectionViewDelegateFlowLayout
let cellId = "CellId"
var categories = [Category]()
let viewOptionVar:ViewOptionBar =
let vOV = ViewOptionBar()
vOV.translatesAutoresizingMaskIntoConstraints = false
return vOV
()
private func fetchData()
let categoryController = CategoryController()
categoryController.getAllCategory(username: "blah", password: "password") (returnedCategories, error) -> Void in
if error != nil
print(error)
return
self.categories = returnedCategories!
print("size of the array is \(self.categories.count)")
override func viewDidLoad()
super.viewDidLoad()
collectionView?.backgroundColor = UIColor.white
collectionView?.register(ItemCell.self, forCellWithReuseIdentifier: cellId)
collectionView?.contentInset = UIEdgeInsetsMake(50, 0, self.view.frame.height, self.view.frame.width)
collectionView?.scrollIndicatorInsets = UIEdgeInsetsMake(50, 0, 0, self.view.frame.width)
collectionView?.dataSource = self
collectionView?.delegate = self
fetchData()
DispatchQueue.main.asyncself.collectionView?.reloadData()
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
print("in the method \(self.categories.count)")
return self.categories.count
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! ItemCell
cell.category = categories[indexPath.item]
return cell
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
return CGSize(width: 111, height: 111)
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat
return 0
private func setupViweOptionBar()
view.addSubview(viewOptionVar)
view.addConstraintsWithFormat(format: "H:|[v0]|", views: viewOptionVar)
view.addConstraintsWithFormat(format: "V:|[v0(50)]", views: viewOptionVar)
编辑 2
以下代码是我的查询方法
func getAllCategory(username:String, password:String, callback: @escaping ([Category]?, String?) -> Void)
var categories = [Category]()
let fetchCategories = URL(string: userURL + "all")
URLSession.shared.dataTask(with: fetchCategories!, completionHandler: (data, response, error) in
if let err = error
print(err)
return
do
let jsonCategoryObj = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [[String: AnyObject]]
for categoryDictionary in jsonCategoryObj
let category = Category()
category.categoryId = categoryDictionary["categoryId"] as? String
category.categoryName = categoryDictionary["categoryName"] as? String
category.categoryDescription = categoryDictionary["categoryDescription"] as? String
let categoryRegisteredDateString = categoryDictionary["categoryRegisteredDate"] as? String
let df = DateFormatter()
df.dateFormat = self.shapeDateFormat
let categoryRegisteredDate = df.date(from: categoryRegisteredDateString!)!
category.categoryRegisteredDate = categoryRegisteredDate
categories.append(category)
callback(categories, nil)
catch let jsonError
callback(nil, String(describing: jsonError))
).resume()
仅供参考:我知道我没有使用传递的用户凭据,这只是我的不同查询方法的复制和粘贴错误
【问题讨论】:
你好。你有没有解决这个问题,或者你只是按照我要的方式给了你? 【参考方案1】:当 DataSource 改变时,reloadData 不会更新视图中已经显示的单元格。重新加载可见项目将完成这项工作。
self.collectionView.reloadData()
self.collectionView.performBatchUpdates( [weak self] in
let visibleItems = self?.collectionView.indexPathsForVisibleItems ?? []
self?.collectionView.reloadItems(at: visibleItems)
, completion: (_) in
)
【讨论】:
【参考方案2】:我不确定这是如何解决这个问题的。但我只是添加了
print("size of the array is \(self.categories?.count)")
就在旁边
OperationQueue.main.addOperationself.collectionView?.reloadData()
它神奇地起作用..甚至认为当我回到屏幕上时,它什么也没显示。
我会进一步调查并尝试找出发生这种情况的原因
更新
使用
DispatchQueue.main.sync
而不是
DispatchQueue.main.async
解决了这个问题。
【讨论】:
你好。我不明白你把那条线放在另一条旁边是什么意思。你的意思是你把这条线放在队列调用之前?【参考方案3】:DispatchQueue.main.asyncself.collectionView?.reloadData()
collectionView?.backgroundColor = UIColor.white
collectionView?.register(ItemCell.self, forCellWithReuseIdentifier: cellId)
在您注册手机之前,您正在重新加载数据。
首先注册您的单元格和数据源并委托方法,最后重新加载数据。
编辑:
我看到你编辑了你的帖子。
但是,在您注册手机之前,您就是fetchData()
。因此,在您注册了所有单元格、数据源和委托之后,再次移动 fetchData
方法。
【讨论】:
这是有道理的。但是,即使我将其更改为collectionView?.backgroundColor = UIColor.white collectionView?.register(ItemCell.self, forCellWithReuseIdentifier: cellId) collectionView?.contentInset = UIEdgeInsetsMake(50, 0, self.view.frame.height, self.view.frame.width) collectionView?.scrollIndicatorInsets = UIEdgeInsetsMake(50, 0, 0, self.view.frame.width) fetchData() DispatchQueue.main.asyncself.collectionView?.reloadData()
,它也不起作用
@J.GS.Han 你没有设置 collectionView.delegate = self 和 collectionView.datasource = self ,我的回答应该更清楚,但这是你现在唯一的问题。另外我认为您需要将 UICollectionViewDataSource 和 UICollectionViewDelegate 添加到您的类中的代码中。
感谢您的回复!我已尝试根据您建议的解决方案更新我的代码,但效果不佳。我还尝试将 UICollectionViewDataSource 和 UICollectionViewDelegate 添加到我的班级,但它抱怨说“'ItemcollectionViewController' 与协议 'UICollectionViewDataSource'' 的冗余一致性”
@J.GS.Han 我看到你正在使用 UICollectionViewController,然后设置 self 就是你所需要的,你应该很高兴。只要确保在 numberOfItemsInSection 方法中更改项目数时调用 reloadData 即可。但是,我无法测试您的代码,因为我没有使用 Swift 编写代码,但通常除了我为您指出的这些错误之外,我看不到任何错误。
我尝试添加 UICollectionViewDataSource 和 UICollectionViewDelegate 作为我班级的超类以上是关于UICollectionView reloadData() 不会更新集合视图中的单元格的主要内容,如果未能解决你的问题,请参考以下文章
带有 TableView 和 CollectionView 的 UiView 不会随机刷新
-[UICollectionView _endItemAnimations] 中的 UICollectionView 断言失败
如何滚动另一个 UICollectionView 下方的 UICollectionView?
UICollectionView 单元内部已加载,但 UICollectionView 未显示
UICollectionView 断言失败 -[UICollectionView _updateWithItems:tentativelyForReordering:]