TableView 嵌套在 CollectionViewCell 中
TableView nested in CollectionViewCell
我正在尝试制作 TableView 的 collectionView,以便每个 table 将包含 "team" 个玩家。 (想法是 Players
按他们的评分平均排序,这样每支球队最后都会持平。无论如何)我在用合适的球员填充 table 时遇到了一些麻烦。 sorting/team-making 代码工作正常,但我无法弄清楚如何从 tableView dataSource 方法中引用每个 table 所在的单元格,我需要填充正确的方法tables 与他们各自的球员。如果您感到困惑,也许下面的代码会阐明我正在尝试做的事情
class myCollectionViewController: UICollectionViewController, UITableViewDelegate, UITableViewDataSource {
//MARK: Properties
//These value are passed by the previous ViewController in PrepareForSegue
var numberOfTeams = Int?() //2
var team = Array<Array<Players>>() //The 2D array of Players which contains the already sorted teams
//for right now this is my temporary solution. See below in TableView Data Source
var collectionIndex = 0
//MARK: UICollectionViewDataSource
override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if numberOfTeams != nil
{return numberOfTeams!}
else
{return 2}
}
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! myCollectionViewCell
cell.teamTable.dataSource = self
cell.teamTable.delegate = self
//teamTable is a UITableView and is set as an Outlet in the CollectionViewCell. Here I'm just setting it
return cell
}
//MARK: TableView DataSource
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
//add correct amount of rows
return team[0].count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
//reset for refresh so index won't go out of bounds of teams Array
if collectionIndex == numberOfTeams
{collectionIndex = 0
print("reset")
}
(这(就在上面)是它失败的地方。视图将正确加载,tables 应该填充。但是如果你滚动到其中一个 tables 的底部,此方法将被调用,并在您再次向上滚动时用错误的数据刷新 table。代码在下面继续)
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! teamTableViewCell
cell.playerName.text = team[collectionIndex][indexPath.row].name
//playerName is a UILabel set as an outlet in the teamTableViewCell class. also, The class Player has a property "name"
//once all players are cycled through, add 1 to collectionIndex
if team[collectionIndex][indexPath.row] === team[collectionIndex].last
{collectionIndex += 1}
return cell
}
}
如上括号所述,当前实现存在问题,只是临时解决方案,因此我可以继续处理代码的其他方面。我需要的是引用 tableView 所在的 collectionViewCell 并更改行
cell.playerName.text = team[collectionIndex][indexPath.row].name
到
cell.playerName.text = team[--"colletionViewCellIndexHere"--][indexPath.row].name
但我不知道如何从 tableview: CellForRowAtIndexPath:
方法
中引用集合单元格 indexPath.item 或行
我试过 tableView.superView
,但没有成功。任何帮助将不胜感激。提前致谢
更好的方法是将管理每个 table 视图的责任交给单独的视图控制器 TeamViewController
。每个 TeamViewController
都有自己的 team
属性,一组玩家。创建集合视图单元格时,添加一个新的 TeamViewController
作为子视图控制器,并将其视图添加为单元格的子视图。只是不要忘记单元格重用 - 您只想将 one TeamViewController
添加到每个单元格。
这样做可以更好地分离逻辑,并使管理您的 table 视图变得更加简单。
编辑:
正确处理单元重用的示例:
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! TeamsCell
embedTeamInTeamsCell(cell, atIndexPath: indexPath)
}
func embedTeamInTeamsCell(cell: TeamsCell, atIndexPath indexPath: NSIndexPath) {
if cell.teamViewController?.team == teams[indexPath.item] {
// The cell already has a team view controller, but it's for the wrong team – remove it
detachTeamFromTeamsCell(cell)
}
if cell.teamViewController == nil {
// The cell doesn't currently have a team view controller – create a new one and add it
let teamVC = self.storyboard?.instantiateViewControllerWithIdentifier("TeamViewController") as! TeamViewController
addChildViewController(teamVC)
cell.addSubview(teamVC.view)
// ... setup constraints on the newly added subview, or set frame
teamVC.didMoveToParentViewController(self)
cell.teamViewController = teamVC
}
}
func detachTeamFromTeamsCell(cell: TeamsCell) {
if let teamVC = cell.teamViewController {
teamVC.willMoveToParentViewController(nil)
cell.teamViewController = nil
teamVC.view.removeFromSuperview()
teamVC.removeFromParentViewController()
}
}
实际上,当您需要更改单元中的嵌入式团队时,重用当前嵌入的 TeamViewController
实例而不是完全丢弃它们可能会更好。然后,只需更改 TeamViewController
上的 team
属性 就足以重新配置该视图控制器以显示新团队(也许您只需要在 team
的 didSet
属性 观察者——取决于你如何构建你的 class):
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! TeamsCell
if cell.teamViewController == nil {
// The cell doesn't currently have a team view controller – create a new one and add it
let teamVC = self.storyboard?.instantiateViewControllerWithIdentifier("TeamViewController") as! TeamViewController
addChildViewController(teamVC)
cell.addSubview(teamVC.view)
// ... setup constraints on the newly added subview, or set frame
teamVC.didMoveToParentViewController(self)
cell.teamViewController = teamVC
}
cell.teamViewController!.team = teams[indexPath.item]
}
class TeamViewController: UITableViewController {
//...
var team: Team? {
didSet { tableView.reloadData() }
}
}
我正在尝试制作 TableView 的 collectionView,以便每个 table 将包含 "team" 个玩家。 (想法是 Players
按他们的评分平均排序,这样每支球队最后都会持平。无论如何)我在用合适的球员填充 table 时遇到了一些麻烦。 sorting/team-making 代码工作正常,但我无法弄清楚如何从 tableView dataSource 方法中引用每个 table 所在的单元格,我需要填充正确的方法tables 与他们各自的球员。如果您感到困惑,也许下面的代码会阐明我正在尝试做的事情
class myCollectionViewController: UICollectionViewController, UITableViewDelegate, UITableViewDataSource {
//MARK: Properties
//These value are passed by the previous ViewController in PrepareForSegue
var numberOfTeams = Int?() //2
var team = Array<Array<Players>>() //The 2D array of Players which contains the already sorted teams
//for right now this is my temporary solution. See below in TableView Data Source
var collectionIndex = 0
//MARK: UICollectionViewDataSource
override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if numberOfTeams != nil
{return numberOfTeams!}
else
{return 2}
}
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! myCollectionViewCell
cell.teamTable.dataSource = self
cell.teamTable.delegate = self
//teamTable is a UITableView and is set as an Outlet in the CollectionViewCell. Here I'm just setting it
return cell
}
//MARK: TableView DataSource
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
//add correct amount of rows
return team[0].count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
//reset for refresh so index won't go out of bounds of teams Array
if collectionIndex == numberOfTeams
{collectionIndex = 0
print("reset")
}
(这(就在上面)是它失败的地方。视图将正确加载,tables 应该填充。但是如果你滚动到其中一个 tables 的底部,此方法将被调用,并在您再次向上滚动时用错误的数据刷新 table。代码在下面继续)
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! teamTableViewCell
cell.playerName.text = team[collectionIndex][indexPath.row].name
//playerName is a UILabel set as an outlet in the teamTableViewCell class. also, The class Player has a property "name"
//once all players are cycled through, add 1 to collectionIndex
if team[collectionIndex][indexPath.row] === team[collectionIndex].last
{collectionIndex += 1}
return cell
}
}
如上括号所述,当前实现存在问题,只是临时解决方案,因此我可以继续处理代码的其他方面。我需要的是引用 tableView 所在的 collectionViewCell 并更改行
cell.playerName.text = team[collectionIndex][indexPath.row].name
到
cell.playerName.text = team[--"colletionViewCellIndexHere"--][indexPath.row].name
但我不知道如何从 tableview: CellForRowAtIndexPath:
方法
我试过 tableView.superView
,但没有成功。任何帮助将不胜感激。提前致谢
更好的方法是将管理每个 table 视图的责任交给单独的视图控制器 TeamViewController
。每个 TeamViewController
都有自己的 team
属性,一组玩家。创建集合视图单元格时,添加一个新的 TeamViewController
作为子视图控制器,并将其视图添加为单元格的子视图。只是不要忘记单元格重用 - 您只想将 one TeamViewController
添加到每个单元格。
这样做可以更好地分离逻辑,并使管理您的 table 视图变得更加简单。
编辑:
正确处理单元重用的示例:
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! TeamsCell
embedTeamInTeamsCell(cell, atIndexPath: indexPath)
}
func embedTeamInTeamsCell(cell: TeamsCell, atIndexPath indexPath: NSIndexPath) {
if cell.teamViewController?.team == teams[indexPath.item] {
// The cell already has a team view controller, but it's for the wrong team – remove it
detachTeamFromTeamsCell(cell)
}
if cell.teamViewController == nil {
// The cell doesn't currently have a team view controller – create a new one and add it
let teamVC = self.storyboard?.instantiateViewControllerWithIdentifier("TeamViewController") as! TeamViewController
addChildViewController(teamVC)
cell.addSubview(teamVC.view)
// ... setup constraints on the newly added subview, or set frame
teamVC.didMoveToParentViewController(self)
cell.teamViewController = teamVC
}
}
func detachTeamFromTeamsCell(cell: TeamsCell) {
if let teamVC = cell.teamViewController {
teamVC.willMoveToParentViewController(nil)
cell.teamViewController = nil
teamVC.view.removeFromSuperview()
teamVC.removeFromParentViewController()
}
}
实际上,当您需要更改单元中的嵌入式团队时,重用当前嵌入的 TeamViewController
实例而不是完全丢弃它们可能会更好。然后,只需更改 TeamViewController
上的 team
属性 就足以重新配置该视图控制器以显示新团队(也许您只需要在 team
的 didSet
属性 观察者——取决于你如何构建你的 class):
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! TeamsCell
if cell.teamViewController == nil {
// The cell doesn't currently have a team view controller – create a new one and add it
let teamVC = self.storyboard?.instantiateViewControllerWithIdentifier("TeamViewController") as! TeamViewController
addChildViewController(teamVC)
cell.addSubview(teamVC.view)
// ... setup constraints on the newly added subview, or set frame
teamVC.didMoveToParentViewController(self)
cell.teamViewController = teamVC
}
cell.teamViewController!.team = teams[indexPath.item]
}
class TeamViewController: UITableViewController {
//...
var team: Team? {
didSet { tableView.reloadData() }
}
}