I have got this Swift code in my project
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: cellid, for: indexPath) as? UITableViewCell
if cell == nil {
cell = UITableViewCell(style: .subtitle, reuseIdentifier: cellid)
}
let user = users[indexPath.row]
cell!.textLabel?.text=user.Name
cell!.detailTextLabel?.text = user.Email
return cell!
}
Everything works fine except that detaiTextLabel is not showing.What is wrong with my code?
My problem was in
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
I should have set style to subtitle like this
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: .subtitle, reuseIdentifier: reuseIdentifier)
}
The problem is its not going inside if condition where you mentioned .subTitle. So I tried of removing if condition it and its working.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: cellid, for: indexPath) as? UITableViewCell
cell = UITableViewCell(style: .subtitle, reuseIdentifier: cellid)
let user = users[indexPath.row]
cell!.textLabel?.text=user.Name
cell!.detailTextLabel?.text = user.Email
return cell!
}
The text in detailTextLabel won't show up if your string is too long to fit inside the label's width. You have 2 options, reduce the size of your string or the font size.
Related
My tableview cell subtitles aren't showing when I use this:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell:UITableViewCell?
if tableView.tag == 1 {
guard let latestCell = tableView.dequeueReusableCell(withIdentifier: "latestCell") else {
return UITableViewCell(style: .subtitle, reuseIdentifier: "latestCell")
}
latestCell.textLabel?.text = latest[indexPath.row]
latestCell.detailTextLabel?.text = latestSub[indexPath.row]
latestCell.accessoryType = .disclosureIndicator
return latestCell
}
}
But then if I use this:
else if tableView.tag == 2 {
let olderCell = UITableViewCell(style: UITableViewCellStyle.subtitle, reuseIdentifier: "olderCell")
olderCell.textLabel?.text = older[indexPath.row]
olderCell.detailTextLabel?.text = olderSub[indexPath.row]
olderCell.accessoryType = .disclosureIndicator
return olderCell
} else {
return cell!
}
}
The subtitles load perfectly, but after I close the app and reload the view, the app autoquits without giving a crash log or taking me to the debugging-tab.
I know that the arrays from which the data comes from are fine, and I think that I've set up everything right in the storyboard. A lot of similar questions have already been posted on the subject, but they all seem to come down to forgetting to set the cellStyle to .subtitle. Thanks in advance for any help I get!
BTW. My regular cell titles are working just like I want them to. No problem there.
EDIT:
I think the problem is that I can create a default-styled cell with no problem. But then when I try to set the style to .subtitle, it loads correctly the first time but when opening the second time, it crashes. Is there a way to use these both declarations together in a way that they don't eliminate each other out;?
guard let latestCell = tableView.dequeueReusableCell(withIdentifier: "latestCell") else {
return UITableViewCell(style: .subtitle, reuseIdentifier: "latestCell")
}
and:
let latestCell = UITableViewCell(style: UITableViewCellStyle.subtitle, reuseIdentifier: "latestCell")
Do it like this:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("latestCell") as UITableViewCell
cell.textLabel?.text = latest[indexPath.row]
cell.detailTextLabel?.text = latestSub[indexPath.row]
cell.accessoryType = .disclosureIndicator
return cell
}
Mark this as solution/upvote if this solved your problem.
Old but...
I think the problem was :
guard let latestCell = tableView.dequeueReusableCell(withIdentifier: "latestCell") else {
return UITableViewCell(style: .subtitle, reuseIdentifier: "latestCell")
}
will return an "empty" cell.
So.. just like :
var latestCell = tableView.dequeueReusableCell(withIdentifier: "latestCell")
if latestCell == nil {
latestCell = UITableViewCell(style: UITableViewCellStyle.subtitle, reuseIdentifier: "latestCell")
}
// your stuff
Ran into this question today as well. I assume the original poster found the answer, but for others that run into this thread in the future here is how I solved this. Note this link/thread explains addition methods of solving as well. How to Set UITableViewCellStyleSubtitle and dequeueReusableCell in Swift?
Environment: Swift 5.0 and Xcode Version 10.2.1.
Explanation: I solved this by subclassing UITabelViewCell and initializing it with the .subtitle type (see code below). Note the .subtitle in the super.init method.
Once you have the subclass don't forget to register CustomCell to your tableView and downcast as CustomCell in your tableView method cellForRowAt.
class CustomCell: UITableViewCell {
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: .subtitle, reuseIdentifier: reuseIdentifier)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Here is the code for the cellForRowAt method, which has the titleLabel and the detailTextLabel(subtitle) properties. Note the downcast "as! CustomCell".
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) ->
UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellId", for:
indexPath) as! CustomCell
cell.textLabel?.text = someArray[indexPath.row].title // Note someArray would have to be replaced with your array of strings.
cell.detailTextLabel?.text = someArray[indexPath.row].subtitle // Note someArray would have to be replaced with your array of strings.
return cell
}
Easiest solution:
Design both cells in Interface Builder directly in the table view(s), set the style and the accessory view to your desired values and add the identifiers.
Then the code can be reduced to.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch tableView.tag {
case 1:
let latestCell = tableView.dequeueReusableCell(withIdentifier: "latestCell" for: indexPath)
latestCell.textLabel!.text = latest[indexPath.row]
latestCell.detailTextLabel!.text = latestSub[indexPath.row]
return latestCell
case 2:
let olderCell = tableView.dequeueReusableCell(withIdentifier: "olderCell" for: indexPath)
olderCell.textLabel!.text = older[indexPath.row]
olderCell.detailTextLabel!.text = olderSub[indexPath.row]
return olderCell
default:
fatalError("That should never happen")
}
}
Since the cells are predefined to subtitle style, both textLabel and detailTextLabel are guaranteed to exist and can be safely unwrapped.
However what is the significant difference between the cells. From the given code you can actually use one cell (identifier cell). That can make the code still shorter:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell" for: indexPath)
if tableView.tag == 1 {
cell.textLabel!.text = latest[indexPath.row]
cell.detailTextLabel!.text = latestSub[indexPath.row]
} else {
cell.textLabel!.text = older[indexPath.row]
cell.detailTextLabel!.text = olderSub[indexPath.row]
}
return cell
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") //replace "Cell" with your identifier
cell.textLabel = yourTitleArray[indexPath.row]
cell.detailTextLabel = yourSubtitleArray[indexPath.row]
return cell!
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "ChatCell")
// put the data
cell.textLabel!.textColor = UIColor.redColor()
cell.textLabel!.textAlignment = .Right
cell.textLabel!.text = array[indexPath.row]
return cell
}
I'm creating and using default UITableViewCell with textAlignment. Right, but it doesn't work.
By the way, Red color works well.
My environment is iOS9 with swift.
Thank you.
Try this
let cell:UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "ChatCell")
instead of
let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "ChatCell")
I'm working in a iOS Swift 2.0 application. I can't figure out for the life of me on how to set the text on the right side of a UITableViewCell just before the disclosure indicator chevron (besides creating a custom cell.accessoryView).
Here is a screenshot of the "Settings app" doing exactly what I'm trying to achieve.
In Interface Builder, when setting up your cell, select the Right Detail style:
Then assign the value to the detailTextLabel property:
cell.detailTextLabel.text = "Kilroy Was Here"
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CellId") ?? UITableViewCell(style: UITableViewCellStyle.value1, reuseIdentifier: "CellId")
cell.accessoryType = UITableViewCellAccessoryType.disclosureIndicator
cell.textLabel?.text = "Main text"
cell.detailTextLabel?.text = "Detail Text"
return cell
}
For anyone trying to do it programmatically without using the storyboard at all, the easiest way would be:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let viewModel = viewModels[indexPath.row]
let cell = UITableViewCell(style: .value1, reuseIdentifier: "cell")
var config = cell.defaultContentConfiguration()
config.text = viewModel.title
config.secondaryText = viewModel.secondaryText
cell.contentConfiguration = config
cell.accessoryType = .disclosureIndicator
return cell
}
I'm trying to pass data from a ViewController to a custom UITableViewCell but it's not working. When I print data from ViewController.swift everything is in tact but when I print data from CustomCell.swift the array is empty. Here is my code:
ViewController.swift
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(kCellIdentifier) as! CustomCell
cell.data = data[indexPath.row]
return cell
}
CustomCell.swift
class CustomCell: UITableViewCell {
var data = [CKRecord]()
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
println(data)
}
}
You can perform that simply by using didSet closure, change your code to the following:
class CustomCell: UITableViewCell {
var data = [Int]() {
didSet{
print(data)
}
}
var id: Int {
didSet{
loadById(id)
}
}
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
// This block runs before data being set! Rather call your code from didSet{} closure..
}
func loadById(_ id: Int) {
// Your code goes here
}
}
And from your ViewController pass the data:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell") as! CustomCell
cell.data = data[indexPath.row]
cell.id = 1 // pass here any variable you need
return cell
}
And it should work
in CustomCell.swift, you just have to set the content such as: UILabel, UIImage, etc.
Rather than explaining here the whole things, I think you better follow the tutorial here:
http://www.ioscreator.com/tutorials/prototype-cells-tableview-tutorial-ios8-swift
if you have more time, this is the deeper one :
http://www.raywenderlich.com/81879/storyboards-tutorial-swift-part-1
good luck! ^_^
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()