I have one custom style UITableviewCell and it have default height for other I am using tableview cell with style of subtitle and I want to make subtitle to be multiple lines. And it's doing good but having problem with calculating tableview cell height and I use UITableviewAutomaticDimension but its not working.
Here is my code
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if(indexPath.row==0){
var cell: ImageCell! = tableView.dequeueReusableCellWithIdentifier("ImageCell") as? ImageCell
if cell == nil {
tableView.registerNib(UINib(nibName: "ImageCell" ,bundle: nil), forCellReuseIdentifier: "ImageCell")
cell = tableView.dequeueReusableCellWithIdentifier("ImageCell") as? ImageCell
}
return cell
}else{
var cell: UITableViewCell? = tableView.dequeueReusableCellWithIdentifier("SubtitleCell")
if (cell == nil) {
cell = UITableViewCell.init(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "SubtitleCell")
cell!.backgroundColor = UIColor.brownColor()
cell!.textLabel?.font = UIFont.init(name: "HelveticaNeue", size: 15)
cell!.textLabel?.textColor = UIColor.blackColor()
cell!.textLabel?.highlightedTextColor = UIColor.lightGrayColor()
cell!.selectedBackgroundView = UIView.init()
}
cell!.textLabel?.text = "TExt"
cell!.detailTextLabel!.text="Keep in mind that UITableView is defined as an optional in the function, which means your initial cell declaration needs to check for the optional in the property. Also, the returned queued cell is also optional, so ensure you make an optional cast to UITableViewCell. Afterwards, we can force unwrap because we know we have a cell."
allowMultipleLines(cell!)
cell!.imageView?.image = UIImage(named: "IconProfile")
return cell!
}
}
func allowMultipleLines(tableViewCell:UITableViewCell) {
tableViewCell.detailTextLabel?.numberOfLines = 0
tableViewCell.detailTextLabel?.lineBreakMode = NSLineBreakMode.ByWordWrapping
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if(indexPath.row==0){
return 172
}else{
return UITableViewAutomaticDimension
}
}
in your viewDidLoad() Method you need to write
yourTableViewName.rowHeight = UITableViewAutomaticDimension
And Add One more method
func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if(indexPath.row==0){
return 172
}else{
return UITableViewAutomaticDimension;
}
}
i hope this will help you
When I selected a row, text color turns white. however, when I scroll to refresh the row, the text color turns back to black. so I have added a logic if(cell.selected). However it didn't work. when I scroll. the code can't get into if case.Here is the code :-
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let selectedCell:UITableViewCell = tableView.cellForRowAtIndexPath(indexPath)!
for subview in selectedCell.subviews {
if let view = subview as? UILabel {
view.textColor = UIColor.whiteColor()
}
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var renderWidth:CGFloat = 8
var renderYPosition:CGFloat = 15
let cell:UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "idcell")
let date = UILabel(frame: CGRectMake(renderWidth, renderYPosition, 110, 20))
let dateText = "asdasdsad"
date.text = dateText
if (cell.selected) {
date.textColor = UIColor.whiteColor()
}
cell.addSubview(date)
}
You are creating a new UITableViewCell everytime. It is recommended to reuse it.
Instead of creating a new cell with this:
let cell:UITableViewCell=UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "idcell")
Use this to reuse the cell:
let cell = tableView.dequeueReusableCellWithIdentifier("cellIdInStoryboard", forIndexPath: indexPath) as! UITableViewCell
The identifier should be the same as the one you set in storyboard.
The problem is with your if clause in cellForRowAtIndexPath function and also you create cell instance everytime you load the tableview.You need to reuse tableview cells.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var renderWidth:CGFloat = 8
var renderYPosition:CGFloat = 15
let cell = tableView.dequeueReusableCellWithIdentifier("idcell", forIndexPath: indexPath) as! YourTableViewCell
let date = UILabel(frame: CGRectMake(renderWidth, renderYPosition, 110, 20))
let dateText = "asdasdsad"
date.text = dateText
if (cell.selected) {
date.textColor = UIColor.whiteColor()
} else {
date.textColor = UIColor.blackColor() // You didn't add else
}
cell.addSubview(date)
}
I have an MGSwipeTableCell added in my tableView like this:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let reuseIdentifier = "Cell"
var cell = tableView.dequeueReusableCellWithIdentifier(reuseIdentifier) as! MGSwipeTableCell!
if cell == nil {
cell = MGSwipeTableCell(style: UITableViewCellStyle.Default, reuseIdentifier: reuseIdentifier)
}
cell.delegate = self
cell.backgroundColor = blue
}
All works fine. But now If I tap the cell the color of the cell changes for maybe a second to white and then to green (default color is blue). This is what should happen if the cell has been pressed:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let mySelectedCell = tableView.cellForRowAtIndexPath(indexPath) as! MGSwipeTableCell!
mySelectedCell.backgroundColor = green
mySelectedCell.detailTextLabel?.text = "Test"
}
So the color should only change to green not to white and then to green and a detailTextLabel with the text "Test" should be displayed.
I hope you can help me to solve this problem. I don't really know what to do.
Solution:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let reuseIdentifier = "Cell"
var cell = tableView.dequeueReusableCellWithIdentifier(reuseIdentifier) as! MGSwipeTableCell!
cell = MGSwipeTableCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: reuseIdentifier)
cell.selectionStyle = UITableViewCellSelectionStyle.None
cell.delegate = self
cell.backgroundColor = blue
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let reuseIdentifier = "Cell"
var cell = tableView.dequeueReusableCellWithIdentifier(reuseIdentifier) as! MGSwipeTableCell!
if cell == nil {
//Change this line
cell = MGSwipeTableCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: reuseIdentifier)
}
//And this line
cell.selectionStyle = UITableViewCellSelectionStyle.None
cell.delegate = self
cell.backgroundColor = blue
}
leave everything as is inside "didSelectRowAtIndexPath"
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()
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!
}
}