UITableView in Swift - uitableview
I'm struggling to figure out what's wrong with this code snippet. This is currently working in Objective-C, but in Swift this just crashes on the first line of the method. It shows an error message in console log: Bad_Instruction.
func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
var cell : UITableViewCell = tableView.dequeueReusableCellWithIdentifier("Cell") as UITableViewCell
if (cell == nil) {
cell = UITableViewCell(style: UITableViewCellStyle.Value1, reuseIdentifier: "Cell")
}
cell.textLabel.text = "TEXT"
cell.detailTextLabel.text = "DETAIL TEXT"
return cell
}
Also see matt's answer which contains the second half of the solution
Let's find a solution without creating custom subclasses or nibs
The real problem is in the fact that Swift distinguishes between objects that can be empty (nil) and objects that can't be empty. If you don't register a nib for your identifier, then dequeueReusableCellWithIdentifier can return nil.
That means we have to declare the variable as optional:
var cell : UITableViewCell?
and we have to cast using as? not as
//variable type is inferred
var cell = tableView.dequeueReusableCellWithIdentifier("CELL") as? UITableViewCell
if cell == nil {
cell = UITableViewCell(style: UITableViewCellStyle.Value1, reuseIdentifier: "CELL")
}
// we know that cell is not empty now so we use ! to force unwrapping but you could also define cell as
// let cell = (tableView.dequeue... as? UITableViewCell) ?? UITableViewCell(style: ...)
cell!.textLabel.text = "Baking Soda"
cell!.detailTextLabel.text = "1/2 cup"
cell!.textLabel.text = "Hello World"
return cell
Sulthan's answer is clever, but the real solution is: don't call dequeueReusableCellWithIdentifier. That was your mistake at the outset.
This method is completely outmoded, and I'm surprised it has not been formally deprecated; no system that can accommodate Swift (iOS 7 or iOS 8) needs it for any purpose whatever.
Instead, call the modern method, dequeueReusableCellWithIdentifier:forIndexPath:. This has the advantage that no optionals are involved; you are guaranteed that a cell will be returned. All the question marks and exclamation marks fall away, you can use let instead of var because the cell's existence is guaranteed, and you're living in a convenient, modern world.
You must, if you're not using a storyboard, register the table for this identifier beforehand, registering either a class or a nib. The conventional place to do that is viewDidLoad, which is as early as the table view exists at all.
Here's an example using a custom cell class:
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.registerClass(MyCell.self, forCellReuseIdentifier: "Cell")
}
// ...
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath:indexPath) as MyCell
// no "if" - the cell is guaranteed to exist
// ... do stuff to the cell here ...
cell.textLabel.text = // ... whatever
// ...
return cell
}
But if you're using a storyboard (which most people do), you don't even need to register the table view in viewDidLoad! Just enter the cell identifier in the storyboard and you're good to go with dequeueReusableCellWithIdentifier:forIndexPath:.
#Sulthan's answer is spot on. One possible convenience modification would be to cast the cell as a UITableViewCell!, rather than a UITableViewCell.
func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
var cell = tableView.dequeueReusableCellWithIdentifier("CELL") as UITableViewCell!
if !cell {
cell = UITableViewCell(style:.Default, reuseIdentifier: "CELL")
}
// setup cell without force unwrapping it
cell.textLabel.text = "Swift"
return cell
}
Now, you can modify the cell variable without force unwrapping it each time. Use caution when using implicitly unwrapped optionals. You must be certain that the value you are accessing has a value.
For more information, refer to the "Implicitly Unwrapped Optionals" section of The Swift Programming Language.
Try this:
func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
cell.textLabel.text = "\(indexPath.row)"
return cell
}
Note that you should register you UITableViewCell and ID when creating instantiating your UITableView:
tableView.delegate = self
tableView.dataSource = self
tableView.registerClass(UITableViewCell.classForCoder(), forCellReuseIdentifier: "Cell")
Here is what I wrote to get it working...
First Register the table view cell with the table view
self.tableView.registerClass(MyTableViewCell.self, forCellReuseIdentifier: "Cell")
Then configure cellForRowAtIndexPath
func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
var cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as MyTableViewCell
cell.textLabel.text = "Cell Text"
cell.detailTextLabel.text = "Cell Detail Text in Value 1 Style"
return cell
}
I then defined a custom cell subclass write at the bottom of the file (since its so much easier now)
class MyTableViewCell : UITableViewCell {
init(style: UITableViewCellStyle, reuseIdentifier: String!) {
super.init(style: UITableViewCellStyle.Value1, reuseIdentifier: reuseIdentifier)
}
}
Here is a simple way to define table cell in swift 2:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let identifier = "cell"
let cell = tableView.dequeueReusableCellWithIdentifier(identifier) ??
UITableViewCell.init(style: UITableViewCellStyle.Default, reuseIdentifier: identifier)
cell.textLabel!.text = "my text"
return cell
}
Swift 3:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let identifier = "cell"
let cell = tableView.dequeueReusableCell(withIdentifier: identifier) ??
UITableViewCell(style: .default, reuseIdentifier: identifier)
cell.textLabel!.text = "my text"
return cell
}
There's a few answers here, but I don't think any of them are ideal, because after the declaration you're ending up with an optional UITableViewCell, which then needs a cell!... in any declarations. I think this is a better approach (I can confirm this compiles on Xcode 6.1):
var cell:UITableViewCell
if let c = tableView.dequeueReusableCellWithIdentifier("cell") as? UITableViewCell {
cell = c
}
else {
cell = UITableViewCell()
}
Well, I have done this way:
Steps for UITableView using Swift:
Take UITableView in ViewController
Give Referencing Outlets in ViewController.swift class
Give Outlets dataSource & delegate to ViewController
Now Swift code in ViewController.swift class:
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var mTableView: UITableView!
var items: [String] = ["Item 1","Item 2","Item 3", "Item 4", "Item 5"]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.mTableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.items.count;
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:UITableViewCell = self.mTableView.dequeueReusableCellWithIdentifier("cell") as! UITableViewCell
cell.textLabel?.text = self.items[indexPath.row]
println(self.items[indexPath.row])
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
println("You have selected cell #\(indexPath.row)!")
}
}
Now it's time to Run your program.
Done
Actually in the Apple's TableView Guide document and Sample Code you will find the sentence below:
If the dequeueReusableCellWithIdentifier: method asks for a cell that’s defined in a storyboard, the method always returns a valid cell. If there is not a recycled cell waiting to be reused, the method creates a new one using the information in the storyboard itself. This eliminates the need to check the return value for nil and create a cell manually.
So,we could just code like this:
var identifer: String = "myCell"
var cell = tableView.dequeueReusableCellWithIdentifier(identifer) as UITableViewCell
cell.textLabel.text = a[indexPath.row].name
cell.detailTextLabel.text = "detail"
I think this is a suitable way to use tableView
Using "as" keyword would do the following two steps:
1.creating a optional value which wrap a variable of UITableViewCell;
2.unwrapping the optional value.
So,by doing this
var cell : UITableViewCell = tableView.dequeueReusableCellWithIdentifier("Component") as UITableViewCell
you would get a "plain" UITableViewCell type variable: cell.Theoretically speaking, it's ok to do this.But the next line
if (cell == nil) {}
makes trouble, because in swift, only the optional value can be assigned with nil.
So, to solve this problem, you have to make cell a variable of Optional type. just like this:
var cell = tableView.dequeueReusableCellWithIdentifier("Component") as? UITableViewCell
using the keyword "as?" would create a Optional variable, and this, undoubtedly, can be assigned with nil.
For cell template:
func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
let myCell : youCell = youCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "cell")
return myCell
}
bro, please take a look at the sample https://github.com/brotchie/SwiftTableView
Why not this?
(please delete if i am not in the goal...)
func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
if let cell: UITableViewCell = theTableView.dequeueReusableCellWithIdentifier("myCell", forIndexPath: indexPath) as? UITableViewCell {
// cell ok
}else{
// not ok
}
}
I have done in following way: to show detailTextLabel. text value
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let CellIdentifier: String = "cell"
var cell = tableView.dequeueReusableCellWithIdentifier(CellIdentifier) as? UITableViewCell
if cell == nil {
cell = UITableViewCell(style: UITableViewCellStyle.Value1, reuseIdentifier: CellIdentifier)
}
//cell.accessoryType = UITableViewCellAccessoryType.DisclosureIndicator
// parse the value of records
let dataRecord = self.paymentData[indexPath.row] as! NSDictionary
let receiverName = dataRecord["receiver_name"] as! String
let profession = dataRecord["profession"] as! String
let dateCreated = dataRecord["date_created"] as! String
let payAmount = dataRecord["pay_amount"] as! String
println("payment \(payAmount)")
cell!.textLabel?.text = "\(receiverName)\n\(profession)\n\(dateCreated)"
cell!.detailTextLabel?.text = "$\(payAmount)"
cell!.textLabel?.numberOfLines = 4
return cell!
}// end tableview
UITableView Demo using Playground
//: Playground - noun: a place where people can play
import UIKit
import PlaygroundSupport
class TableviewDemoDelegate:NSObject,UITableViewDataSource,UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 100
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell:UITableViewCell? = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath as IndexPath)
if cell == nil {
cell = UITableViewCell(style: .default, reuseIdentifier: "cell")
}
cell?.textLabel?.text = "Item \(indexPath.row+1)"
return cell!
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("You have selected cell #\(indexPath.row)!")
}
}
var tableView = UITableView(frame:CGRect(x: 0, y: 0, width: 320, height: 568), style: .plain)
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
let delegate = TableviewDemoDelegate()
tableView.delegate = delegate
tableView.dataSource = delegate
PlaygroundPage.current.liveView = tableView
I went through your codes and most probably the reason for the crash is you are trying to typecast an optional value which is not assigned
Now consider the line of code below
var cell : UITableViewCell = tableView.dequeueReusableCellWithIdentifier("Cell") as UITableViewCell
When there are no cells in the tableview you are still trying to typecast as UITableView.When the compiler tries to typecast nil value you face this issue
The correct statement should be
var cell : UITableViewCell = tableView.dequeueReusableCellWithIdentifier("Cell")
You can use if else statement to typecast for values which holds
Try this code
var cell:CustomTableViewCell = tableView.dequeueReusableCellWithIdentifier("CustomTableViewCell") as CustomTableViewCell
cell.cellTitle.text="vijay"
https://github.com/iappvk/TableView-Swift
Related
Cannot assign value of type 'UITableViewCell' to type '...Cell' error in swift
let cellIdentifier = "ChampionThumbnailCell" override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { var cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as? ChampionThumbnailTableViewCell if cell == nil { cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: cellIdentifier) } cell!.championNameLabel.text = championNames[indexPath.row] cell!.championThumbnailImageView.image = UIImage(named: championThumbnail[indexPath.row]) return cell! } I want to use the above code to reuse UITableViewCell, but I got this error when build it. It looks like thie: Cannot assign value of type 'UITableViewCell' to type 'ChampionThumbnailTableViewCell?' Is there any solution could fix it? (By the way, I'm not very good at English...)
Change your method to this: override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cellIdentifier = "ChampionThumbnailCell" var cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! ChampionThumbnailTableViewCell cell.championNameLabel.text = championNames[indexPath.row] cell.championThumbnailImageView.image = UIImage(named: championThumbnail[indexPath.row]) return cell } Notice in third line I am using as! instead of as? showing compiler that you aren't confused about your cell being nil. But if it turns out that your cell is nil, it should cause runtime error.
Value of type 'FormBaseCell' has no member
I'm new in xcode programming and came across this error. I'm not sure what the new updated xcode wants me to do here since it worked before I upgraded. The error: Value of type 'FormBaseCell' has no member. My code: override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let rowDescriptor = formRowDescriptorAtIndexPath(indexPath) let formBaseCellClass = formBaseCellClassFromRowDescriptor(rowDescriptor) let reuseIdentifier = NSStringFromClass(formBaseCellClass) var cell: FormBaseCell? = tableView.dequeueReusableCellWithIdentifier(reuseIdentifier) as? FormBaseCell if cell == nil { cell = formBaseCellClass.init(style: .Default, reuseIdentifier: reuseIdentifier) cell?.tableViewController = self // <--error cell?.configure() }
I'm not sure where you got this code from. I have never seen anyone go through all these steps to get a cell. You should just be able to do this: override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { // Set up your table and prototype cell on storyboard let reuseIdentifier = "MyCell" var cell: FormBaseCell? = tableView.dequeueReusableCellWithIdentifier(reuseIdentifier) as? FormBaseCell if let cell = cell { cell.textLabel.text = "something" } else { cell = FormBaseCell() } return cell }
UITableViewCell not showing detailTextLabel.text - Swift
The detail (subtitle) text does not appear. The data are available, though, because when a println() call is added, it prints Optional("data") to the console with the expected data. In the storyboard, the UITableViewController is set to the proper class, the Table View Cell Style is set to 'Subtitle', and the reuse identifier is set to 'cell'. How can I get the subtitle information to display? override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { var cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as UITableViewCell dispatch_async(dispatch_get_main_queue(), { () -> Void in cell.textLabel.text = self.myArray[indexPath.row]["title"] as? String cell.detailTextLabel?.text = self.myArray[indexPath.row]["subtitle"] as? String println(self.myArray[indexPath.row]["subtitle"] as? String) // The expected data appear in the console, but not in the iOS simulator's table view cell. }) return cell }
Your code looks fine. Just goto the storyboard and select the cell of your tableview -> Now goto Attributes Inspector and choose the style to Subtitle. Follow this according to the below screenshot. Hope it helped..
Same issue here (from what I've read, perhaps a bug in iOS 8?), this is how we worked around it: Delete the prototype cell from your storyboard Remove this line: var cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as UITableViewCell Replace with these lines of code: let cellIdentifier = "Cell" var cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier) as? UITableViewCell if cell == nil { cell = UITableViewCell(style: UITableViewCellStyle.Value2, reuseIdentifier: cellIdentifier) } Update for Swift 3.1 let cellIdentifier = "Cell" var cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier) if cell == nil { cell = UITableViewCell(style: UITableViewCellStyle.value2, reuseIdentifier: cellIdentifier) } Update for Swift 4.2 - Simplified let cell = UITableViewCell(style: UITableViewCell.CellStyle.value2, reuseIdentifier: "cellId") Update for Swift 5 - Simplified let cell = UITableViewCell(style: .value2, reuseIdentifier: "cellId")
If you still want to use prototype cell from your storyboard, select the TableViewcell style as Subtitle. it will work.
Try this it work for me (swift 5) let cell = UITableViewCell(style: .value1, reuseIdentifier: "cellId") cell.textLabel.text = "Déconnexion" cell.imageView.image = UIImage(named: "imageName") Objective c : UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:#"cellId"];
If you are setting the text to nil somewhere when you try to set it to a non-nil value the actual view that contains the text will be missing. This was introduced in iOS8. Try setting to an empty space #" " character instead. See this: Subtitles of UITableViewCell won't update
If doing so programmatically without cells in interface builder this code works like a charm in Swift 2.0+ override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. yourTableView.delegate = self yourTableView.dataSource = self yourTableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "subtitleCell") } func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return yourTableViewArray.count } func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! { let cell: UITableViewCell = yourTableView.dequeueReusableCellWithIdentifier("subtitleCell", forIndexPath: indexPath) as UITableViewCell cell.textLabel?.text = "the text you want on main title" cell.detailTextLabel?.text = "the text you want on subtitle" return cell }
For what it's worth: I had the problem of detail not appearing. That was because I had registered the tableView cell, which I should not have done as the cell prototype was defined directly in storyboard.
In Xcode11 and Swift5 , We have to do like below. If we do it by checking the condition cell == nil and then creating UITableViewCell with cellStyle it is not working . Below solution is working for me . func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cellIdentifier = "Cell" let cell = UITableViewCell(style: UITableViewCell.CellStyle.subtitle, reuseIdentifier: cellIdentifier) cell?.textLabel?.text = "Title" cell?.detailTextLabel?.text = "Sub-Title" return cell! }
Here is how it works for swift 5, to get a subtitle using detailtextlabel, using a UITableView object within a view controller, if you are missing any of these, it will not work and will probably crash. class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource In viewDidLoad: tableView.register(UITableViewCell.self, forCellReuseIdentifier: "subtitleCell") Delegate Function: func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { // Fetch a cell of the appropriate type. let cell = UITableViewCell(style: .subtitle , reuseIdentifier: "subtitleCell") // Configure the cell’s contents. cell.textLabel!.text = "Main Cell Text" cell.detailTextLabel?.text = "Detail Cell Text" return cell }
xcode 11 override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { // let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath) let cell = UITableViewCell(style: UITableViewCell.CellStyle.value1, reuseIdentifier: "reuseIdentifier") cell.detailTextLabel?.text = "Detail text" cell.textLabel?.text = "Label text" // Configure the cell... return cell }
Some of the solutions above are not entirely correct. Since the cell should be reused, not re-created. You can change init method. final class CustomViewCell: UITableViewCell { override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: .value1, reuseIdentifier: reuseIdentifier) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } }
Three properties will be deprecated in a future release: imageView textLabel and detailTextLabel You can use UIListContentConfiguration to configure cell dataSource = UITableViewDiffableDataSource(tableView: tableview, cellProvider: { tableview, indexPath, menu in let cell = tableview.dequeueReusableCell(withIdentifier: self.profileCellIdentifier, for: indexPath) var content = cell.defaultContentConfiguration() content.text = menu.title if indexPath.section == MenuSection.info.rawValue { content.image = UIImage(systemName: "person.circle.fill") content.imageProperties.tintColor = AppColor.secondary } if let subtitle = menu.subTitle { content.secondaryText = subtitle } cell.contentConfiguration = content return cell })
Swift 5 with subtitle text, here no need to register your cell in viewDidLoad: var cell = tableView.dequeueReusableCell(withIdentifier: "cell") if cell == nil { cell = UITableViewCell(style: UITableViewCell.CellStyle.subtitle, reuseIdentifier: "cell") } cell?.textLabel?.text = "title" cell?.textLabel?.numberOfLines = 0 cell?.detailTextLabel?.text = "Lorem ipsum" cell?.detailTextLabel?.numberOfLines = 0 return cell ?? UITableViewCell()
Unabled to change UITableViewCell properties
I'm trying to change the accessory view / accessory type of my table view cells, but it doesn't work. func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { var cell: UITableViewCell? switch indexPath.row { case 0: cell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "enabledCell") cell!.textLabel?.text = "Alarm enabled" var enabledSwitch = UISwitch(frame: CGRectZero) cell!.accessoryView = enabledSwitch case 1: cell = self.tableView.dequeueReusableCellWithIdentifier("calendarCell", forIndexPath: indexPath) as? UITableViewCell cell!.textLabel?.text = "Calendar" cell!.accessoryType = UITableViewCellAccessoryType.DisclosureIndicator default: cell = self.tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as? UITableViewCell cell!.textLabel?.text = "Oops" } return cell! }
I am not sure why this isnt working for you. I created a new project. Made a ViewController with a tableView in it and copied/pasted your code. Works. I get 1 cell with a switch, another with a disclosure, and one with no accessor. Is your table working at all? If your app just crashes maybe your reuseIdentifiers are misspelled or something. Maybe you didnt link your tableView to your ViewController as the delegate/datasource. Good Luck! import Foundation import UIKit class MyTableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { #IBOutlet var tableView: UITableView! override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int{ return 3 } func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{ var cell: UITableViewCell? switch indexPath.row { case 0: cell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "enabledCell") cell!.textLabel?.text = "Alarm enabled" var enabledSwitch = UISwitch(frame: CGRectZero) cell!.accessoryView = enabledSwitch case 1: cell = self.tableView.dequeueReusableCellWithIdentifier("calendarCell", forIndexPath: indexPath) as? UITableViewCell cell!.textLabel?.text = "Calendar" cell!.accessoryType = UITableViewCellAccessoryType.DisclosureIndicator default: cell = self.tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as? UITableViewCell cell!.textLabel?.text = "Oops" } return cell! } }
PFTableViewCell not changing labelText
The below code is supposed to take the name field from the PFObject being passed into cellForRowAtIndexPath and set the textLabel.text field to the name (ie the tableView row could potentially read "sneeze1"). I'm able to change the height of each row with the heightForRowAtIndexPath method and also see the correct number of calls to cellForRowAtIndexPath (3 rows loaded into a class on Parse's Data Browser in my specific case) with the right fields, but I can't get the textLabel.text to change. Is there some other step that needs to be completed before a textLabel can have its text changed? override func tableView(tableView: UITableView!, heightForRowAtIndexPath indexPath: NSIndexPath!) -> CGFloat { return 60 } override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!, object: PFObject!) -> PFTableViewCell! { var cellIdentifier = "EventCell" var cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as? PFTableViewCell if !cell { cell = PFTableViewCell(style: .Subtitle, reuseIdentifier: cellIdentifier) } var name = object["name"] as? String cell!.textLabel.text = name println("textLabel: \(cell!.textLabel.text)" + " name: \(name)") return cell }
You must use the original delegate signature, else your method won't get called. Instead of override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!, object: PFObject!) -> PFTableViewCell! use override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell!
The issue is that as? returns an optional type, so name is of type String?. Try this instead if you really want to handle missing names: if let name = object["name"] as? String { cell!.textLabel.text = name }
I was able to get the text to change when I set used the UITableViewCell cellForRowAtIndexPath. It looks like the problem is with Parse's PFTableViewCell potentially mixing with Swift. It's not allowing me to change the text on PFTableViewCell. As a side note, the code works even when the below method exists in my PFQueryTableViewController side-by-side with the above PFTableViewCell cellForRowAtIndexPath. Somehow, the code is actually just running the UITableViewCell cellForRowAtIndexPath method instead. override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! { var cellIdentifier = "EventCell" var cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as? UITableViewCell if !cell { cell = UITableViewCell(style: .Subtitle, reuseIdentifier: cellIdentifier) } var name = "HELLO"//object["name"] as? String cell!.textLabel.text = name println("textLabel: \(cell!.textLabel.text)" + " name: \(name)") //cell.imageView.file = object.objectForKey(self.imageKey) as PFFile return cell }