可靠地使用 UICollectionView indexPath 访问字典键?
Reliably using UICollectionView indexPath to access dictionary keys?
我正在尝试使用当前 CollectionViewcell 的 IndexPath 访问字典中的数据。字典的键是 Int 类型。
这个 CollectionView 有 "full page" 个单元格,这意味着每个单元格占据了我使用水平滚动(启用分页)在单元格之间导航的完整视图区域。
字典是:
var dataFromServer: [Int: [VillageFestival]]?
每个 CollectionViewCell 内部都有一个 TableView,我计划其中的行数可变,具体取决于 [VillageFestival]
中的项目数量
然而,在 CollectionView cellForItemAt indexPath
中,该方法的行为引起了一些麻烦,如打印 indexPath.item 或将其设置为我的 navigationController 的标题,returns 奇怪但 "understandable"结果给出了我认为 dequeueReusableCell 是如何工作的?...
示例:当前索引为0。当我向右滚动时,当前索引现在为2。如果我导航到第6页,然后返回一页,则当前索引为3。
我已将我的字典键从 Date 更改为 String,现在更改为 Int,以试图简化逻辑。但问题仍然存在。
我正在使用正在 CollectionView cellForItemAt
内部更新的全局 pageIndex: Int
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
pageIndex = indexPath.item
self.navigationController?.navigationBar.topItem?.title = String(pageIndex)
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionViewCell", for: indexPath) as! CollectionViewCell
// CollectionViewCell resize to CollectionView Bounds
cell.tableViewCellOffsets = (UIApplication.shared.statusBarFrame.size.height + (self.navigationController?.navigationBar.frame.height ?? 0.0) , self.tabBarController?.tabBar.frame.height ?? 0)
return cell
}
在 Tableview numberOfRowsInSection 中,我使用 pageIndex 访问字典值。
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
guard let festivals = dataFromServer?[pageIndex] else {return 0}
return festivals.count
}
使用我当前的代码,该应用程序为某些页面显示 0 行,为其他页面显示 1 行。我的猜测是 collectionView 的 cellForItemAt 在 tableView 的方法之前(也可能在之后?)被调用,这使得使用全局 pageIndex 变得不可靠...
谢谢!
试试这个 playground,它可能对你有帮助:
import UIKit
import PlaygroundSupport
class Cell: UICollectionViewCell, UITableViewDataSource {
var data: [Int]! = [] {
didSet {
tableView.reloadData()
}
}
private let tableView: UITableView
override init(frame: CGRect) {
tableView = UITableView(frame: .zero, style: .plain)
super.init(frame: frame)
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
tableView.dataSource = self
tableView.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(tableView)
NSLayoutConstraint.activate([
tableView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
tableView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
tableView.topAnchor.constraint(equalTo: contentView.topAnchor),
tableView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor)
])
}
required init?(coder aDecoder: NSCoder) {
fatalError()
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = String(data[indexPath.item])
return cell
}
}
class VC: UICollectionViewController {
let data = [
0: [1, 2, 3, 4, 5],
1: [6, 4],
2: [5, 5, 5, 5, 6],
3: [9, 9, 8, 4, 5, 5, 5]
]
override init(collectionViewLayout layout: UICollectionViewLayout) {
super.init(collectionViewLayout: layout)
collectionView.isPagingEnabled = true
collectionView.register(Cell.self, forCellWithReuseIdentifier: "Cell")
}
required init?(coder aDecoder: NSCoder) {
fatalError()
}
override func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return data.count
}
override func viewDidLayoutSubviews() {
(collectionViewLayout as? UICollectionViewFlowLayout)?.itemSize = collectionView.bounds.size
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! Cell
cell.data = data[indexPath.item]
return cell
}
}
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
PlaygroundPage.current.liveView = VC(collectionViewLayout: layout)
我正在尝试使用当前 CollectionViewcell 的 IndexPath 访问字典中的数据。字典的键是 Int 类型。 这个 CollectionView 有 "full page" 个单元格,这意味着每个单元格占据了我使用水平滚动(启用分页)在单元格之间导航的完整视图区域。
字典是:
var dataFromServer: [Int: [VillageFestival]]?
每个 CollectionViewCell 内部都有一个 TableView,我计划其中的行数可变,具体取决于 [VillageFestival]
中的项目数量然而,在 CollectionView cellForItemAt indexPath
中,该方法的行为引起了一些麻烦,如打印 indexPath.item 或将其设置为我的 navigationController 的标题,returns 奇怪但 "understandable"结果给出了我认为 dequeueReusableCell 是如何工作的?...
示例:当前索引为0。当我向右滚动时,当前索引现在为2。如果我导航到第6页,然后返回一页,则当前索引为3。
我已将我的字典键从 Date 更改为 String,现在更改为 Int,以试图简化逻辑。但问题仍然存在。
我正在使用正在 CollectionView cellForItemAt
pageIndex: Int
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
pageIndex = indexPath.item
self.navigationController?.navigationBar.topItem?.title = String(pageIndex)
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionViewCell", for: indexPath) as! CollectionViewCell
// CollectionViewCell resize to CollectionView Bounds
cell.tableViewCellOffsets = (UIApplication.shared.statusBarFrame.size.height + (self.navigationController?.navigationBar.frame.height ?? 0.0) , self.tabBarController?.tabBar.frame.height ?? 0)
return cell
}
在 Tableview numberOfRowsInSection 中,我使用 pageIndex 访问字典值。
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
guard let festivals = dataFromServer?[pageIndex] else {return 0}
return festivals.count
}
使用我当前的代码,该应用程序为某些页面显示 0 行,为其他页面显示 1 行。我的猜测是 collectionView 的 cellForItemAt 在 tableView 的方法之前(也可能在之后?)被调用,这使得使用全局 pageIndex 变得不可靠...
谢谢!
试试这个 playground,它可能对你有帮助:
import UIKit
import PlaygroundSupport
class Cell: UICollectionViewCell, UITableViewDataSource {
var data: [Int]! = [] {
didSet {
tableView.reloadData()
}
}
private let tableView: UITableView
override init(frame: CGRect) {
tableView = UITableView(frame: .zero, style: .plain)
super.init(frame: frame)
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
tableView.dataSource = self
tableView.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(tableView)
NSLayoutConstraint.activate([
tableView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
tableView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
tableView.topAnchor.constraint(equalTo: contentView.topAnchor),
tableView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor)
])
}
required init?(coder aDecoder: NSCoder) {
fatalError()
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = String(data[indexPath.item])
return cell
}
}
class VC: UICollectionViewController {
let data = [
0: [1, 2, 3, 4, 5],
1: [6, 4],
2: [5, 5, 5, 5, 6],
3: [9, 9, 8, 4, 5, 5, 5]
]
override init(collectionViewLayout layout: UICollectionViewLayout) {
super.init(collectionViewLayout: layout)
collectionView.isPagingEnabled = true
collectionView.register(Cell.self, forCellWithReuseIdentifier: "Cell")
}
required init?(coder aDecoder: NSCoder) {
fatalError()
}
override func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return data.count
}
override func viewDidLayoutSubviews() {
(collectionViewLayout as? UICollectionViewFlowLayout)?.itemSize = collectionView.bounds.size
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! Cell
cell.data = data[indexPath.item]
return cell
}
}
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
PlaygroundPage.current.liveView = VC(collectionViewLayout: layout)