I made a table view with collapsing cells I followed this tutorial; everything works great, except for the segue method. I simply tried to add performsegueWithIdentifier
method (adding the segue in the storyboard by the cell)
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
performSegueWithIdentifier("toChantController", sender: self)
}
and prepareForSegue
method:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
if segue.identifier == "toChantController"
{
let indexPath = tableView.indexPathForCell(sender as! UITableViewCell)
let controller = segue.destinationViewController as! ChantViewController
controller.chant = "\(sections[indexPath!.row])"
}
}
but Xcode sends me this error
"Could not cast value of type 'iSupporters.TeamChantViewController' (0x104562730) to 'UITableViewCell' (0x106600540)."
Here my whole class:
import UIKit
class TeamChantViewController: UIViewController, UITableViewDataSource, UITableViewDelegate
{
// MARK: properties
var teamChants: TeamModel!
@IBOutlet weak var tableView: UITableView!
struct Section {
var name: String!
var items: [String]!
var collapsed: Bool!
init(name: String, items: [String], collapsed: Bool = true) {
self.name = name
self.items = items
self.collapsed = collapsed
}
}
var sections = [Section]()
override func viewDidLoad()
{
super.viewDidLoad()
tableView.backgroundColor = UIColor.clearColor()
tableView.separatorColor = UIColor.clearColor()
sections = [
Section(name: "Juventus", items: ["Olè", "fino alla fine", "ovunque voi giocate", "juve olè"]),
Section(name: "Derby", items: ["toro merda", "odio i granata", "il viola è il colore che odio"]),
Section(name: "Giocatori", items: ["Vidal", "Pogba", "Del Piero"])
]
}
override func viewWillAppear(animated: Bool)
{
super.viewWillAppear(animated)
self.tabBarController?.tabBar.hidden = true
}
// MARK: collection view data source and delegate
func numberOfSectionsInTableView(tableView: UITableView) -> Int
{
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
var count = sections.count
for section in sections
{
count += section.items.count
}
return count
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
{
let section = getSectionIndex(indexPath.row)
let row = getRowIndex(indexPath.row)
if row == 0 {
return 50.0
}
return sections[section].collapsed! ? 0 : 44.0
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let section = getSectionIndex(indexPath.row)
let row = getRowIndex(indexPath.row)
if row == 0
{
let cell = tableView.dequeueReusableCellWithIdentifier("teamChantsHeader") as! TeamChantsHeader
cell.teamChantSectionTitle.text = sections[section].name
cell.toggleButton.tag = section
cell.toggleButton.setTitle(sections[section].collapsed! ? "+" : "-", forState: .Normal)
cell.toggleButton.addTarget(self, action: #selector(TeamChantViewController.toggleCollapse), forControlEvents: .TouchUpInside)
return cell
} else {
let cell = tableView.dequeueReusableCellWithIdentifier("teamChantsCell") as UITableViewCell!
cell.textLabel?.text = sections[section].items[row - 1]
return cell
}
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
performSegueWithIdentifier("toChantController", sender: self)
print(self)
}
// MARK: navigation (segue)
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
if segue.identifier == "toChantController"
{
let indexPath = tableView.indexPathForCell(sender as! UITableViewCell)
let controller = segue.destinationViewController as! ChantViewController
controller.chant = "\(sections[indexPath!.row])"
}
}
// MARK: - other methods
func toggleCollapse(sender: UIButton)
{
let section = sender.tag
let collapsed = sections[section].collapsed
// Toggle collapse
sections[section].collapsed = !collapsed
let indices = getHeaderIndices()
let start = indices[section]
let end = start + sections[section].items.count
tableView.beginUpdates()
for i in start ..< end + 1
{
tableView.reloadRowsAtIndexPaths([NSIndexPath(forRow: i, inSection: 0)], withRowAnimation: .Automatic)
}
tableView.endUpdates()
}
func getSectionIndex(row: NSInteger) -> Int
{
let indices = getHeaderIndices()
for i in 0..<indices.count
{
if i == indices.count - 1 || row < indices[i + 1]
{
return i
}
}
return -1
}
func getRowIndex(row: NSInteger) -> Int
{
var index = row
let indices = getHeaderIndices()
for i in 0..<indices.count
{
if i == indices.count - 1 || row < indices[i + 1]
{
index -= indices[i]
break
}
}
return index
}
func getHeaderIndices() -> [Int]
{
var index = 0
var indices: [Int] = []
for section in sections
{
indices.append(index)
index += section.items.count + 1
}
return indices
}
}
Could anyone help me to perform this segue?
You are doing here two things,
UITableViewCell
to ChantViewController
.didSelectRowAtIndexPath
you are performing segue again with passing self
as reference of TeamChantViewController
.You need to change any one thing to solved your problem.
Edit: From your comment you need to pass indexPath object with sender
parameter in performSegue
method like this and get that indexPath in prePareForSegue
method.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
performSegueWithIdentifier("toChantController", sender: indexPath)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "toChantController"
{
let indexPath = sender as! NSIndexPath
let controller = segue.destinationViewController as! ChantViewController
controller.chant = "\(sections[indexPath!.row])"
}
}