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"
Related
In the application, I have custom protocols that my UIViewController conforms to. I have a custom tableViewCell class and have UIImageView and UITextView in there. I set the cell's delegate to the UIViewController after dequeuing. However only one of the custom protocols makes the callback (imagepicker protocol).
protocol customProtocol1{
func pickImage(myInt: Int)
}
protocol customProtocol2{
func protocol2 (myInt: Int)
}
class controller1: UIViewController, UITableViewDelegate, customProtocol1, customProtocol2 {
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section:Int) -> Int {
return 3
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeReusableCellWithIdentifier("customCell", forIndexPath: indexPath) as! CustomTableCellClass
cell.delegate = self
return cell
}
func pickImage ( myInt: Int){
print("This line prints")
}
func protocol2 (myInt: Int){
print ("This line doesn't print")
}
}
And here's the customTableCellClass code:
class CustomTableCellClass: UITableViewCell, UITextFieldDelegate, UITextViewDelegate {
var imageDelegate: customProtocol1?
#IBAction func pickImage( sender: AnyObject) {
imageDelagate?.pickImage(205)
}
var somethingElseDelegate: customProcotol2?
#IBActon func clickOnButton( sender: AnyObject) {
print("this line prints")
somethingElseDelegate?.protocol2(2)
}
override func awakeFromNib(){
super.awakeFromNib()
}
}
My question is, why does the first protocol get callbacks but second does not?
From what I see in your code, you only set one delegate, change your code in cellForRowAtIndexPath to
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeReusableCellWithIdentifier("customCell", forIndexPath: indexPath) as! CustomTableCellClass
cell.imageDelegate = self
cell.somethingElseDelegate = self
return cell
}
Your custom cell has two delegate properties, imageDelegate and somethingElseDelegate, but in your implementation of tableView(tableView:cellForRowAtIndexPath:) you only assign one property.
If you set both properties your implementation should work.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = tableView.dequeReusableCellWithIdentifier("customCell", forIndexPath: indexPath) as! CustomTableCellClass
cell.imageDelegate = self
cell.somethingElseDelegate = self
return cell
}
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"
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)
}
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()
}
So, I'm getting a 'Type ViewController does not conform to protocol UITableViewDataSource' error in Xcode. I've implemented the required functions:
cellForRowAtIndexPath
numberOfRowsInSection
I've even made sure I've told Xcode how many sections there are (which is not required). This is a Single View Application and I have ensured my references are setup correctly in Storyboard. So my Outlets are my view and my table view. My Referencing Outlets are set for dataSource and delegate to be my Table View.
Here's the code.
ViewController.swift
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
var items: [String] = ["We", "Dislike", "Swift", "Very", "Much", "Right", "Now"]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")
tableView.delegate = self
tableView.dataSource = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int{
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.items.count
}
func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
let cell:UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath:indexPath) as UITableViewCell
cell.textLabel?.text = self.items[indexPath.row]
return cell
}
func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!) {
println("You selected cell #\(indexPath.row)!")
}
}
EDIT: Also, I know that I shouldn't need the tableView.delegate and tableView.dataSource as I have assigned them in the Storyboard but I thought I'd include them to make sure you all know that I know to have them set.
UITableViewDataSource protocol has changed a little bit. Try:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
Your tableView(tableView:cellForRowAtIndexPath) signature is wrong - it should be:
func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell {
let cell:UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath:indexPath) as UITableViewCell
cell.textLabel?.text = self.items[indexPath.row]
return cell
}
Note that it doesn't return an optional value (i.e., no ! suffix) any more.