UICollectionView 中的单元格重叠
Cells overlapping in UICollectionView
我在具有动态大小的单元格的 UICollectionView 中显示对自定义 API 的 Web 请求的结果。但是,当我在获取数据后调用 reloadSections 时,许多单元格显示重叠。
滚动视图时,单元格会显示在适当的位置。
我已经追踪到在我的 Web 请求的完成块中调用 reloadSections 的错误。使用硬编码文本,集合视图可以正确显示初始布局。如果在完成块中调用 reloadSections,则会发生错误。下面是相关代码:
override func viewDidLoad() {
super.viewDidLoad()
collectionView.register(UINib.init(nibName: "ExhibitionsCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "ExhibitionsCollectionViewCell")
layout.estimatedItemSize = CGSize(width: 1, height: 1)
collectionView.dataSource = exhibitionsDataSource
collectionView.delegate = self
store.fetchExhibitions {
(exhibitionsResult) -> Void in
switch exhibitionsResult {
case let .success(exhibitions):
print("Successfully found \(exhibitions.count) exhibitions.")
if exhibitions.first != nil {
self.exhibitionsDataSource.exhibitions = exhibitions
}
case let .failure(error):
print("Error fetching exhibitions: \(error)")
self.exhibitionsDataSource.exhibitions.removeAll()
}
// this is the line that produces the erroneous layout
self.collectionView.reloadSections(IndexSet(integer: 0))
}
}
发出网络请求的代码:
func fetchExhibitions(completion: @escaping (ExhibitionsResult) -> Void) {
let url = WebAPI.exhibitionsURL
let request = URLRequest(url: url)
let task = session.dataTask(with: request) {
(data, response, error) -> Void in
let result = self.processExhibitionsRequest(data: data, error: error)
OperationQueue.main.addOperation {
completion(result)
}
}
task.resume()
}
如果有任何其他代码有助于回答这个问题,请告诉我。
更新: 我通过实现 UICollectionViewDelegateFlowLayout
的以下委托方法解决了这个问题
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let cell = collectionView.cellForItem(at: indexPath)
let height = cell?.contentView.bounds.height ?? 1
let width = cell?.contentView.bounds.width ?? 1
return CGSize(width: width, height: height)
}
Update2: 将我的假 Lorem Ipsum 数据换成从服务器实际检索到的数据后,问题再次出现。但是,我终于能够通过切换行
来解决问题
self.collectionView.reloadSections(IndexSet(integer: 0))
至
self.reloadData()
我认为 reloadSection(_:) 只是执行与 reloadData() 相同的操作,但对于选定的部分和文档似乎没有另外说明......但无论哪种方式现在都有效!
从那个代码我不确定原因,但也许尝试实现委托 UICollectionViewDelegateFlowLayout.
提供的一些功能
关注函数
sizeForItemAtIndexPath
示例:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
return CGSizeMake(320, 500);
}
我在具有动态大小的单元格的 UICollectionView 中显示对自定义 API 的 Web 请求的结果。但是,当我在获取数据后调用 reloadSections 时,许多单元格显示重叠。
滚动视图时,单元格会显示在适当的位置。
我已经追踪到在我的 Web 请求的完成块中调用 reloadSections 的错误。使用硬编码文本,集合视图可以正确显示初始布局。如果在完成块中调用 reloadSections,则会发生错误。下面是相关代码:
override func viewDidLoad() {
super.viewDidLoad()
collectionView.register(UINib.init(nibName: "ExhibitionsCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "ExhibitionsCollectionViewCell")
layout.estimatedItemSize = CGSize(width: 1, height: 1)
collectionView.dataSource = exhibitionsDataSource
collectionView.delegate = self
store.fetchExhibitions {
(exhibitionsResult) -> Void in
switch exhibitionsResult {
case let .success(exhibitions):
print("Successfully found \(exhibitions.count) exhibitions.")
if exhibitions.first != nil {
self.exhibitionsDataSource.exhibitions = exhibitions
}
case let .failure(error):
print("Error fetching exhibitions: \(error)")
self.exhibitionsDataSource.exhibitions.removeAll()
}
// this is the line that produces the erroneous layout
self.collectionView.reloadSections(IndexSet(integer: 0))
}
}
发出网络请求的代码:
func fetchExhibitions(completion: @escaping (ExhibitionsResult) -> Void) {
let url = WebAPI.exhibitionsURL
let request = URLRequest(url: url)
let task = session.dataTask(with: request) {
(data, response, error) -> Void in
let result = self.processExhibitionsRequest(data: data, error: error)
OperationQueue.main.addOperation {
completion(result)
}
}
task.resume()
}
如果有任何其他代码有助于回答这个问题,请告诉我。
更新: 我通过实现 UICollectionViewDelegateFlowLayout
的以下委托方法解决了这个问题 func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let cell = collectionView.cellForItem(at: indexPath)
let height = cell?.contentView.bounds.height ?? 1
let width = cell?.contentView.bounds.width ?? 1
return CGSize(width: width, height: height)
}
Update2: 将我的假 Lorem Ipsum 数据换成从服务器实际检索到的数据后,问题再次出现。但是,我终于能够通过切换行
来解决问题self.collectionView.reloadSections(IndexSet(integer: 0))
至
self.reloadData()
我认为 reloadSection(_:) 只是执行与 reloadData() 相同的操作,但对于选定的部分和文档似乎没有另外说明......但无论哪种方式现在都有效!
从那个代码我不确定原因,但也许尝试实现委托 UICollectionViewDelegateFlowLayout.
提供的一些功能关注函数
sizeForItemAtIndexPath
示例:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
return CGSizeMake(320, 500);
}