Table view didselectrowatindex returning nil (Swift) - ios

I have a UITableViewController that has a function named didselectrowatindex that should return the text on a cell, but it returns nil. How can I return the text of the selected cell in Swift UITableViewController?
class TableViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let indexPath = tableView.indexPathForSelectedRow();
let currentCell = tableView.cellForRowAtIndexPath(indexPath!) as UITableViewCell!;
println(currentCell.textLabel!.text)
}
}
EDIT: I forgot to mention that I am using static cells, which means the data is already set so I didn't think there was a need for cellforrowatindex.

It looks like you need to implement cellForRowAtIndexPath
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("cell")
let text = self.tableContents[indexPath.row] as! String
//tableContents is just the array from which you're getting what's going in your tableView, and should be declared outside of your methods
cell.textLabel?.text = text
return cell
}
also add
self.tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")
into you viewDidLoad
hope this helps!
Edit for static cells:
Okay, so looking at it that way, maybe try to replace the line
let currentCell = tableView.cellForRowAtIndexPath(indexPath!) as UITableViewCell!;
with
let currentCell = super.tableView(self.tableView, cellForRowAtIndexPath: indexPath)
and get rid of the line above it as suggested by Lancelot in a comment on your question.
Edit Two:
I used the following code and it works:
class TableViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let currentCell = super.tableView(self.tableView, cellForRowAtIndexPath: indexPath)
let text: String = currentCell.textLabel!.text as String!
print(text)
}
}

If you have your data source array of the titles as:
var arrTitlesDataSource = ["t1","t2","t3"]
So you are using them in order to set the title at the cellForRowlike this:
cell.textLabel?.text = arrTitlesDataSource[indexPath.row]
Than you may get the title in this way:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var title = arrTitlesDataSource[indexPath.row]
println(title)
}

Get selected row cell from tableView(sender) and then
get your data from selected cell.
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
var currentCell= tableView.cellForRowAtIndexPath(indexPath)! as tableViewCell
println(currentCell.textLabel!.text)
}

Related

Method does not override any method from it's superclass (error) [duplicate]

I have created a slide out menu using Swift. I have done this many times before, but when I created it today, I get this error (see screenshot). It could just be a simple mistake I have made.
Here is the code, that I think is causing the problem:
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
var cell:UITableViewCell? = tableView.dequeueReusableCellWithIdentifier("Cell")! as UITableViewCell
if cell == nil{
cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
cell!.backgroundColor = UIColor.clearColor()
cell!.textLabel!.textColor = UIColor.darkTextColor()
let selectedView:UIView = UIView(frame: CGRect(x: 0, y: 0, width: cell!.frame.size.width, height: cell!.frame.size.height))
selectedView.backgroundColor = UIColor.blackColor().colorWithAlphaComponent(0.3)
cell!.selectedBackgroundView = selectedView
}
cell!.textLabel!.text = tableData[indexPath.row]
return cell
}
Screenshot:
UPDATE: I have tried removing override
Hope someone can help!
The method does not override any method of the superclass because the signature is wrong.
The correct signature is
override func tableView(tableView: UITableView,
cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
All parameters are non-optional types.
And use also the recommended method
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier,
forIndexPath: indexPath)
which also returns always a non-optional type
Make sure that your class implements UITableViewDelegate and UITableViewDataSource.
class MyController: UIViewController, UITableViewDelegate, UITableViewDataSource {
// All your methods here
}
You won't need override keyword unless any other superclass already implements those methods.
See this works for me
Just confirm UITableViewDelegate and UITableViewDataSource
Implement required methods
import UIKit
class ListViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
let containArray = ["One","two","three","four","five"]
// MARK: - View Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//MARK: Table view data source and delegate methods
//Number of rows
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return containArray.count
}
//Prepare Custom Cell
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
let identifier = "simpleTextCell"
var cell: SimpleTextCell! = tableView.dequeueReusableCellWithIdentifier(identifier) as? SimpleTextCell
if cell == nil {
tableView.registerNib(UINib(nibName: "SimpleTextCell", bundle: nil), forCellReuseIdentifier: identifier)
cell = tableView.dequeueReusableCellWithIdentifier(identifier) as? SimpleTextCell
}
let dayName = containArray[indexPath.row]
cell.lblProductName.text = dayName
return cell
}
//Handle click
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("productListSegue", sender: self)
}
}
Try to removing "!", declaration for this function is:
func tableView(_ tableView: UITableView,cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
and make sure you have set delegate and datasource of tableview to "self"

How to use checkmark for UITableView

I am trying to create a simple todo list app for learning purposes i. I want to be able to click on a row and add a check mark and when clicked again i want it to go away. i have looked at several other examples but nothing is working. How can i achieve this?
class FirstViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tbView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tbView.reloadData()
}
override func viewWillAppear(animated: Bool) {
self.tbView.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return tasks.manager.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "Default Tasks")
//Assign the contents of our var "items" to the textLabel of each cell
cell.textLabel!.text = tasks.manager[indexPath.row].name
cell.detailTextLabel!.text = tasks.manager[indexPath.row].time
return cell
}
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath){
if (editingStyle == UITableViewCellEditingStyle.Delete){
tasks.manager.removeAtIndex(indexPath.row)
tbView.reloadData()
}
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let cell = tableView.cellForRowAtIndexPath(indexPath)
cell!.accessoryType = .Checkmark
tableView.reloadData()
}
}
To put it simply, you can use this code.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if let cell = tableView.cellForRowAtIndexPath(indexPath)
if (cell!.accessoryType == .Checkmark) {
cell!.accessoryType = .None
} else {
cell!.accessoryType = .Checkmark
}
tableView.reloadData()
}
This way, when you re-select cell, the checkmark will adjust accordingly.
However, you shouldn't modify cell checkmark this way as the cell will get re used when you scroll.
You need to update your data model instead it above approach.
so in your data model, add new property to hold checkmark state and then use it in cellForRowAtIndexPath function.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "Default Tasks")
//Assign the contents of our var "items" to the textLabel of each cell
cell.textLabel!.text = tasks.manager[indexPath.row].name
cell.detailTextLabel!.text = tasks.manager[indexPath.row].time
if tasks.manager[indexPath.row].isSelected { //assume that isSelected is bool
cell!.accessoryType = .Checkmark
} else {
cell!.accessoryType = .None
}
return cell
}
and then in your didSelectRowAtIndexPath update the model.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let dataModel = tasks.manager[indexPath.row]
dataModel.isSelected = !dataModel.isSelected
tableView.reloadData()
}
I'm assuming that you are using a table view in a storyboard. If that's the case, in the attributes inspector, you can choose a chick mark as the style.
You'll need both didSelectRowAtIndexPath and didDeselectRowAtIndexPath methods of the UITableViewDelegate protocol.
You can simple use them like this!
Deselect
func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
let cell = tableView.cellForRowAtIndexPath(indexPath)
cell!.accessoryType = .None
//tableView.reloadData()
}
Select
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let cell = tableView.cellForRowAtIndexPath(indexPath)
cell!.accessoryType = .Checkmark
//tableView.reloadData()
}

Swift: Table view superclass error

I have created a slide out menu using Swift. I have done this many times before, but when I created it today, I get this error (see screenshot). It could just be a simple mistake I have made.
Here is the code, that I think is causing the problem:
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
var cell:UITableViewCell? = tableView.dequeueReusableCellWithIdentifier("Cell")! as UITableViewCell
if cell == nil{
cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
cell!.backgroundColor = UIColor.clearColor()
cell!.textLabel!.textColor = UIColor.darkTextColor()
let selectedView:UIView = UIView(frame: CGRect(x: 0, y: 0, width: cell!.frame.size.width, height: cell!.frame.size.height))
selectedView.backgroundColor = UIColor.blackColor().colorWithAlphaComponent(0.3)
cell!.selectedBackgroundView = selectedView
}
cell!.textLabel!.text = tableData[indexPath.row]
return cell
}
Screenshot:
UPDATE: I have tried removing override
Hope someone can help!
The method does not override any method of the superclass because the signature is wrong.
The correct signature is
override func tableView(tableView: UITableView,
cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
All parameters are non-optional types.
And use also the recommended method
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier,
forIndexPath: indexPath)
which also returns always a non-optional type
Make sure that your class implements UITableViewDelegate and UITableViewDataSource.
class MyController: UIViewController, UITableViewDelegate, UITableViewDataSource {
// All your methods here
}
You won't need override keyword unless any other superclass already implements those methods.
See this works for me
Just confirm UITableViewDelegate and UITableViewDataSource
Implement required methods
import UIKit
class ListViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
let containArray = ["One","two","three","four","five"]
// MARK: - View Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//MARK: Table view data source and delegate methods
//Number of rows
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return containArray.count
}
//Prepare Custom Cell
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
let identifier = "simpleTextCell"
var cell: SimpleTextCell! = tableView.dequeueReusableCellWithIdentifier(identifier) as? SimpleTextCell
if cell == nil {
tableView.registerNib(UINib(nibName: "SimpleTextCell", bundle: nil), forCellReuseIdentifier: identifier)
cell = tableView.dequeueReusableCellWithIdentifier(identifier) as? SimpleTextCell
}
let dayName = containArray[indexPath.row]
cell.lblProductName.text = dayName
return cell
}
//Handle click
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("productListSegue", sender: self)
}
}
Try to removing "!", declaration for this function is:
func tableView(_ tableView: UITableView,cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
and make sure you have set delegate and datasource of tableview to "self"

how to expand or replace the cell with another cell, when an particular cell select in table view

I have already asked this doubt/problem in SO. but not get get solution. Please help me out....
i have one table view which will show the list of name data till 10 datas. But what i need is , when user press any cell, that cell should be replace with another cell, which have some image, phone number, same data name. How to do that.
I have two xib : 1. normalcell, 2. expandable/replace cell
Here is my viewconrolelr.swift
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var Resultcount: UILabel!
var tableData = ["thomas", "Alva", "Edition", "sath", "mallko", "techno park",... till 10 data]
let cellSpacingHeight: CGFloat = 5
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
var nib = UINib(nibName:"customCell", bundle: nil)
tableView.registerNib(nib, forCellReuseIdentifier: "cell")
Resultcount.text = "\(tableData.count) Results"
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return self.tableData.count
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return cellSpacingHeight
}
// Make the background color show through
func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = UIView()
headerView.backgroundColor = UIColor.clearColor()
return headerView
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:customCell = self.tableView.dequeueReusableCellWithIdentifier("cell") as! customCell
cell.vendorName.text = tableData[indexPath.section]
return cell
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Starting my cell will look like this :
When i press that cell, i need some thing to do like this with replace ment of like below cell :
But when i press same cell again, again it should go to normal cell.
How to do that ??
First modify your tableView:cellForRowAtIndexPath: implementation as follows. Then you need to implement the click handler. One way would be in the MyCell class. Another would be to override selectRowAtIndexPath. Without knowing more about what you want (e.g. multiple vs single selection), it's hard to give actual code but here's something.
BOOL clickedRows[MAX_ROWS]; // Init this array as all false in your init method. It would be better to use NSMutableArray or something similar...
// selectRowAtIndexPath code
int row = indexPath.row
if(clickedRows[row]) clickedRows[row]=NO; // we reverse the selection for the row
else clickedRows[row]=YES;
[self.tableView reloadData];
// cellForRowAt... code
MyCell *cell = [tableView dequeueResuableCell...
if(cell.clicked) { // Nice Nib
[tableView registerNib:[UINib nibWithNibName... for CellReuse...
} else { // Grey Nib
[tableView registerNib:[UINib nibWithNibName... for CellReuse...
}
You need to create two independent cell on xib. Then you can load using check.You can copy and paste it will work perfectly.
in cellForRowAt like this:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if selectedIndexPath == indexPath && self.isExpand == true{
let cell = tableView.dequeueReusableCell(withIdentifier: "LeaveBalanceExpandedCell", for: indexPath) as! LeaveBalanceExpandedCell
cell.delegate = self
return cell
}
else{
let cell = tableView.dequeueReusableCell(withIdentifier: "LeaveBalanceNormalCell", for: indexPath) as! LeaveBalanceNormalCell
return cell
}
}
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
// cell.animateCell(cell)
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if selectedIndexPath == indexPath{
if isExpand == true{
self.isExpand = false
}
else{
self.isExpand = true
}
}
else{
selectedIndexPath = indexPath
self.isExpand = true
}
self.tableView.reloadData()
}

re-populating a tableview with new array elements when a cell is clicked in swift

thanks for all the help so far. I need, when a cell in UITableView is clicked, to re-populate the view with an array read from another class - just can find a way to refresh the view. Code as follows:
Thanks in advance - the help so far has been great for this newbie.
import UIKit
class SecondViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet var tableView: UITableView!
let textCellIdentifier = "TextCell"
var catRet = XnYCategories.mainCats("main")
//var catRet = XnYCategories.subCats("Sport")
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
// MARK: UITextFieldDelegate Methods
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return catRet.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(textCellIdentifier, forIndexPath: indexPath) as! UITableViewCell
let row = indexPath.row
cell.textLabel?.text = catRet[row]
return cell
}
// MARK: UITableViewDelegate Methods
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
let row = indexPath.row
//let currentCell = tableView.cellForRowAtIndexPath(indexPath)
//var selectedText = currentCell!.textLabel?.text
//println(selectedText)
let catRet2 = XnYCategories.mainCats(catRet[row])
println(catRet2)
println(catRet[row])
//catRet = catRet2
}
}
Call reloadData() on your tableView as follow
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
let row = indexPath.row
//let currentCell = tableView.cellForRowAtIndexPath(indexPath)
//var selectedText = currentCell!.textLabel?.text
//println(selectedText)
let catRet2 = XnYCategories.mainCats(catRet[row])
println(catRet2)
println(catRet[row])
// *** New code added ***
// remove the comment
catRet = catRet2
// call reloadData()
tableView.reloadData()
// *** New code added ***
}
just do this:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
let row = indexPath.row
catRet = XnYCategories.mainCats(catRet[row])
tableView.reloadData()
}

Resources