Custom UITableViewCell not showing labels - ios

I've created custom cell view in Xcode:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! FeedCell
let iniStr = self.tableArray[indexPath.row]
let fullNameArr = iniStr.components(separatedBy: "||1||")
let daFirst = fullNameArr[0]
let daSecond = fullNameArr[1]
let finalco = daSecond.components(separatedBy: "||2||")
let fString = finalco[0]
cell.questionLabel?.text = daFirst
cell.answerLabel?.text = daSecond
return cell
}
class FeedCell: UITableViewCell {
#IBOutlet weak var questionLabel: UILabel!
#IBOutlet weak var answerLabel: UILabel!
}
then hooked up everything in storyboard, set constraints and registered class: self.tableView.register(FeedCell.self, forCellReuseIdentifier: "Cell")
When I use Subtitle as class of my custom table cell everything works fine, but when I use custom FeedCell in my table cell, label's are not showing, but I am able to select cells.

Try this code to debug connections
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! FeedCell
let iniStr = self.tableArray[indexPath.row]
print(iniStr)
let fullNameArr = iniStr.components(separatedBy: "||1||")
let daFirst = fullNameArr[0]
let daSecond = fullNameArr[1]
print(daFirst)
print(daSecond)
let finalco = daSecond.components(separatedBy: "||2||")
let fString = finalco[0]
cell.questionLabel?.text = daFirst
cell.answerLabel?.text = daSecond
cell.questionLabel.backgroundColor = .red
cell.answerLabel.backgroundColor = .green
return cell
}

Related

Swift. How to edit two different label in TableViewCell for each cell?

I have TableView which has cells with 2 label. I want to set value for both label during load operation. However, I have no access to both labels.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let fr = fractionList[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "FrictionCell", for: indexPath) as! SwipeTableViewCell
cell.delegate = self
cell.textLabel?.text = fr.fraction
//cell.textLabel?.text = fr.decimal
cell.backgroundColor = UIColor(hexString: fr.color ?? "#FFFFFF")
return cell
}
you can't have two labels with the same name so you can rename the outlet for your labels to have two outlets in your cell SwipeTableViewCell :
#IBOutlet weak var lblFractionOutlet: UILabel!
#IBOutlet weak var lblDecimalOutlet: UILabel!
and then you can access them in function cellForRowAt:
cell.lblFractionOutlet.text = fr.fraction
cell.lblDecimalOutlet.text = fr.decimal
I hope it will work with you...

Increment Label Value with UIStepper in UITableViewCell

I want to be able to use a UIStepper that is located in each tableview row. I would like each UIStepper to update a label in the same tableview row that the UIStepper is in.
The code that I am trying is as follows
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cartListCell = tableView.dequeueReusableCell(withIdentifier: reuseCartListingCellIdentifier, for: indexPath) as? CartListingItemTableViewCell
cartListCell?.UI_STEPPER_NAME.value = VALUE_FROM_ARRAY
return cartListCell!
}
#IBAction func CartStoreQtyStepperAction(_ sender: UIStepper) {
// I need to update the value of a label in the tableview cell that tapped
}
UPDATED IMPLEMENTATION
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
cartListCell?.CartListingProductQtyStepperOutlet.tag = indexPath.row
cartListCell?.CartListingProductQtyStepperOutlet.addTarget(self, action: #selector(self.CartStoreQtyStepperAction(_:)), for: UIControlEvents.valueChanged)
cartListCell?.tag = Int(CartStoreItemIdArray [indexPath.row])!
return cartListCell!
}
#IBAction func CartStoreQtyStepperAction(_ sender: UIStepper)
{
let stepperValue = Int(sender.value)
let indexPath = IndexPath(row: stepperValue, section: 0)
print(stepperValue)
if let cell = yourTableView.cellForRow(at: indexPath) as? CartListingItemTableViewCell
{
print(cell?.tag)
}
}
I am not able to access the tableview cell and the label in that when I am doing it like this. Can someone guide me how to do this?
// Custom tableview cell code
class CartListingItemTableViewCell: UITableViewCell {
#IBOutlet weak var label: UILabel!
#IBOutlet weak var stepper: UIStepper!
}
// your view controller code (tableview data source)
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cartListCell = tableView.dequeueReusableCell(withIdentifier: reuseCartListingCellIdentifier, for: indexPath) as? CartListingItemTableViewCell
let stepperValue = yourArray[indexPath.row]
cartListCell?.label.text = String(stepperValue) ?? "0"
cartListCell?.stepper.value = Int(stepperValue) ?? 0
cartListCell?.stepper.tag = indexPath.row
cartListCell?.stepper.addTarget(self, action: #selector(self.stepperValueChanged(_:)), for: UIControlEvents.valueChanged)
return cartListCell!
}
// handle stepper value change action
#IBAction func stepperValueChanged(_ stepper: UIStepper) {
let stepperValue = Int(stepper.value)
print(stepperValue) // prints value
let indexPath = IndexPath(row: stepperValue, section: 0)
if let cell = yourTableView.cellForRow(at: indexPath) as? CartListingItemTableViewCell {
cell.label.text = String(stepperValue)
yourValueArray[index] = stepperValue
}
}
This is a solution for Swift 4 using NSKeyValueObservation
First of all you need a property in your data model to keep the current value of the stepper.
var counter = 0.0
In the custom cell create outlets for the stepper and the label and a property for the observation. Connect the outlets.
#IBOutlet weak var stepper : UIStepper!
#IBOutlet weak var label : UILabel!
var observation : NSKeyValueObservation?
In the controller in cellForRow add the observer, dataSourceArray is the data source array.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cartListCell = tableView.dequeueReusableCell(withIdentifier: reuseCartListingCellIdentifier, for: indexPath) as! CartListingItemTableViewCell
let item = dataSourceArray[indexPath.row]
cartListCell.stepper.value = item.counter
cartListCell.label.text = "\(item.counter)"
cartListCell.observation = cell.stepper.observe(\.value, options: [.new]) { (_, change) in
cartListCell.label.text = "\(change.newValue!)"
item.counter = change.newValue!
}
return cartListCell
}
Solution for Swift 4 swift4.
Add these lines in cellforRowAt.
cartListCell.UI_STEPPER_NAME.tag = indexPath.row
cartListCell.UI_STEPPER_NAME.addTarget(self, action: #selector(CartStoreQtyStepperAction), for: .touchUpInside)
To access cell items in the stepper function use this line.
let cartListCell = sender.superview?.superview as! CartListingItemTableViewCell
//check whether your superview is table cell.
//then use the cell instance to update the cell label
Use sender.tag in the function to access particular cell for example.
cartListCell.UI_STEPPER_NAME.text = "\(VALUE_FROM_ARRAY[sender.tag])"
//sender.tag is similar to indexPath.row as we pass the tag value in the cellforRowAt.
//It will work then please accept my answer๐Ÿ‘๐Ÿผ๐Ÿ˜„.
Assign tag value to sender of UIStepper in cellForRowAt and access the change of UIStepper value in CartStoreQtyStepperAction action using same tag.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cartListCell = tableView.dequeueReusableCell(withIdentifier: reuseCartListingCellIdentifier, for: indexPath) as? CartListingItemTableViewCell
//Assign tag value
cartListCell?.UI_STEPPER_NAME.tag = indexPath.row
cartListCell?.UI_STEPPER_NAME.value = VALUE_FROM_ARRAY
cartListCell?.stepper.addTarget(self, action: #selector(self.CartStoreQtyStepperAction(_:)), for: UIControlEvents.valueChanged)
return cartListCell!
}
#IBAction func CartStoreQtyStepperAction(_ sender: UIStepper) {
let index = sender.tag
yourValueArray[index] = sender.value
//Reload particular cell for tableView
}

Tableview cell reusability, cutting label texts

Here I attached the gif file. Refer this
In my tableview I have a custom xib cell with autolayout. When I run the project, getting the problem like the gif file.
Its my tableview function
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "requestsCell", for: indexPath) as? RequestsTableViewCell
cell?.backgroundColor = .clear
let passengerName = cell?.viewWithTag(1) as! UILabel
let bookingCreator = cell?.viewWithTag(2) as! UILabel
let department = cell?.viewWithTag(3) as! UILabel
let product = cell?.viewWithTag(4) as! UILabel
passengerName.text = "Muhammed yasheed"
bookingCreator.text = "Muhammed Yasheed"
department.text = "Programming"
product.text = "Flight"
cell?.approvedView.isHidden = false
cell?.cancelView.isHidden = true
return cell!
}
Finally I found the answer. Just add cell?.layoutIfNeeded() in cellForRowAt indexpath
cell?.layoutIfNeeded()

UITableView checkmarks duplicated

I keep getting checkmarks being marked in other sections of my table view when I click a row. Im not certain if I need to set my accessoryType. I tried mytableView.reloadData() however that didn't help either.
var selected = [String]()
var userList = [Users]()
#IBOutlet weak var myTableView: UITableView!
#IBAction func createGroup(_ sender: Any) {
for username in self.selected{
ref?.child("Group").childByAutoId().setValue(username)
print(username)
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let myCell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! MyTableViewCell
myCell.selectionStyle = UITableViewCellSelectionStyle.none
myCell.nameLabel.text = userList[indexPath.row].name
return myCell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if myTableView.cellForRow(at: indexPath)?.accessoryType == UITableViewCellAccessoryType.checkmark{
myTableView.cellForRow(at: indexPath)?.accessoryType = UITableViewCellAccessoryType.none
let currentUser = userList[indexPath.row]
selected = selected.filter { $0 != currentUser.name}
}
else{
myTableView.cellForRow(at: indexPath)?.accessoryType = UITableViewCellAccessoryType.checkmark
let currentUser = userList[indexPath.row]
selected.append(currentUser.name!)
}
}
Your problem is not inside this method but in the one that "loads" the cells. (cell for row)
Since Table Views use reusable cells, more often than not they will be loading a cell that was already presented somewhere else.
Because of this, on the cell loading method you should "Reset the state" the loaded cell, this includes the accessory type, and any other properties you might have changed.
So just change this in your code:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let myCell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! MyTableViewCell
myCell.selectionStyle = UITableViewCellSelectionStyle.none
myCell.nameLabel.text = userList[indexPath.row].name
// ADD THIS
if userList[indexPath.row].isSelected {
myCell.accessoryType = UITableViewCellAccessoryType.checkmark
} else {
myCell.accessoryType = UITableViewCellAccessoryType.none
}
return myCell
}
EDIT:
"userList[indexPath.row].isSelected" is a property that YOU have to create and manage. (So you must also modify it in the didSelectRowAt method.
The issue is you are not maintaining the selected User info properly, which will be used while you scroll the table and when the cell has to reload data.
As you have already created var selected = [String]() , I suggest using the same.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let myCell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! MyTableViewCell
let dataFoundInselectedArr = selected.filter { $0 == userList[indexPath.row].name}
if(dataFoundInselectedArr.count > 0){
myCell.accessoryType = UITableViewCellSelectionStyle.checkmark
}else{
myCell.accessoryType = UITableViewCellSelectionStyle.none
}
myCell.nameLabel.text = userList[indexPath.row].name
return myCell
}
The table selection delegate method remains the same.

"Generate" labels from data swift

I have
["06:58"]
["07:13", "07:38", "07:53"]
["08:13", "08:38", "08:53"]
["09:13", "09:33", "09:53"]
and I want to show it in tableView as in picture:
every element - it's UILabel, I created class TimeViewCell: UITableViewCell where have property var labels = [UILabel]() but I don't know how to push data from my array in my function:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellTime", for: indexPath) as! TimeViewCell
let showHour = self.infoWripper.sorted(by: { $0.hour < $1.hour })
cell.labelTime.text = showHour[indexPath.row].showHour()
for data in showHour {
print(data.showFullTime()) //here you see my example of data in console
}
return cell
}
I would add a UIStackView to your UITableViewCell. You can add the labels with the text to the UIStackView.
I wrapped your data into an array.
let tableViewData = [["06:58"],
["07:13", "07:38", "07:53"],
["08:13", "08:38", "08:53"],
["09:13", "09:33", "09:53"]]
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellTime", for: indexPath) as! TimeViewCell
cell.configure(data: tableViewData[indexPath.row])
return cell
}
Then, in for your TimeViewCell, you have to add your UIStackView IBOulet (or add it programmatically) and the configure method.
class TimeViewCell: UITableViewCell {
#IBOutlet var labelStackView: UIStackView!
func configure(data: Array<String>) {
for time in data {
let timeLabel = UILabel()
timeLabel.text = time
labelStackView.addArrangedSubview(label)
}
}
}

Resources