Swift progressBar filling on every cell-click - swift

Each of my cells in tableView has its own progressBar which is being filled in cellForRowAt method and it works fine.
My problem is whenever I select a cell, it's progress bar refreshes filling.
Does anyone have an idea why and how to prevent it? I think didSelectRowAt method is not a reason because that method does nothing with the progressBar.
Method for filling progressBar:
func updateProgressBar(_ cell: TestTableViewCell, level: String) {
let cellCards = Float64(self.getNumberOfCardsForLevel(level: level))!
let totalCards = Float64(self.totalCards())!
delay(0.3) {
cell.cellProgress.setProgress(Float(cellCards / totalCards), animated: true)
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TestTableViewCell", for: indexPath) as! TestTableViewCell
cell.accessoryType = .disclosureIndicator;
cell.cellProgress.progress = 0
cell.cellTitle.text = "Test"
cell.numOfCardsInCell.text = getNumberOfCardsForLevel(level: "1")
updateProgressBar(cell, level: "1")
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.tableView.indexPathsForSelectedRows?.forEach { index in
if(self.cellSelectedImage[indexPath.row] == UIImage(named: "imageTwo") ) {
tableView.deselectRow(at: indexPath, animated: false)
self.cellSelectedImage[indexPath.row] = UIImage(named: "imageOne")
}
else {
print("Selected row -> \(index.row)")
if self.cellSelectedImage[indexPath.row] == UIImage(named: "imageTwo") {
self.cellSelectedImage[indexPath.row] = UIImage(named: "imageOne")
}
}
}
tableView.reloadRows(at: [indexPath], with: .automatic)
}

Related

tableview cell needs to reset core data entities when deleted

in my swift code below when one tableview cell is deleted the tableview cells after is not showing a change in the place of the number. So when 2 is deleted what is left is 1 and 3 it should just state 1 and 2. I listed my code below with the delete function.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let title = itemName[indexPath.row]
let cell = theScores.dequeueReusableCell(withIdentifier: "MyCell", for : indexPath)
cell.selectionStyle = .default
if let position = title.value(forKey: "positon") {
cell.textLabel?.text = "Item : \(title.positon))"
}
cell.textLabel?.text = "Item: \(title.positon)"
cell.textLabel?.textAlignment = .center
cell.layoutMargins = UIEdgeInsets.zero
cell.preservesSuperviewLayoutMargins = false
cell.separatorInset = UIEdgeInsets.zero
cell.layoutMargins = UIEdgeInsets.zero
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return itemName.count
}
var itemName : [Player] = []
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == UITableViewCell.EditingStyle.delete {
let appd = UIApplication.shared.delegate as! AppDelegate
let context = appd.persistentContainer.viewContext
context.delete(itemName[indexPath.row])
itemName.remove(at: indexPath.row)
do {
try context.save()
}
catch {
print("d")
}
self.theScores.reloadData()
}
}

How to change image in imageview when tableview cell is expand and collapse in swift

I am using two images for cell, one i am showing when tableview cell is expand and the other one when cell is collapse
when cell expand i am using arrow-bottom
when cell is collapse arrow-right
for cell expand and collapse i am using below code:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
let cell = tableView.cellForRow(at: indexPath) as! FAQTableVIewCell
if selectedIndex == indexPath.row{
if self.isCollapse == false{
cell.arrowImage.image = UIImage(named: "arrow-rightt")
self.isCollapse = true
}else{
cell.arrowImage.image = UIImage(named: "arrow-bottom")
self.isCollapse = false
}
}else{
self.isCollapse = true
}
self.selectedIndex = indexPath.row
tableView.reloadRows(at: [indexPath], with: .automatic)
}
but the above code not working properly, first time when i expand cell its not showing bottom arrow, and if i expand two cells then also its not showing properly, pls do help with code
i need when cell expand then i need to show bottom-arrow, when cell in normal(back to its orginal position or collapsed position) then i need to show right-arrow
When you reload rows, they get in cellForRowAt method.
You must apply changes in this method. Store collapsed indexPath and check it in method.
With array:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//use your cell identifier
let cell = tableView.dequeueReusableCell(withIdentifier: "FAQTableVIewCell", for: indexPath) as! FAQTableVIewCell
let image = collapsedCells.contains(indexPath) ? UIImage(named: "arrow-rightt") : UIImage(named: "arrow-bottom")
cell.image = image
//other settings
return cell
}
var collapsedCells = [IndexPath]()
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
//use your height values instead 44 and 120
return collapsedCells.contains(indexPath) ? 44 : 120
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
if let index = collapsedCells.firstIndex(of: indexPath) {
collapsedCells.remove(at: index)
} else {
collapsedCells.append(indexPath)
}
tableView.reloadRows(at: [indexPath], with: .automatic)
}

How to disable/enable notifications in tablewiew by using UISwitch in Swift

I am working on a location-based reminder app. I show all reminders that user created on a table view. I have also UISwitch on every cell. I want that UISwitch disables/enables reminders individually, not all notifications. I couldn't figure it out.
extension MainViewController: UITableViewDataSource{
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 100
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.items?.count ?? 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//let cell = tableView.dequeueReusableCell(withIdentifier: "itemCell", for: indexPath)
let cell = tableView.dequeueReusableCell(withIdentifier: "itemCell", for: indexPath) as! itemTableViewCell
let item = self.items![indexPath.row]
cell.itemTitle?.text = item.itemName
cell.itemSubTitle?.text = item.itemDescription
//switch
let swicthView = UISwitch(frame: .zero)
swicthView.onTintColor = UIColor (named: "DingerBlue")
swicthView.setOn(true, animated: true)
swicthView.tag = indexPath.row
swicthView.addTarget(self, action: #selector(self.SwitchBtn(_:)), for: .valueChanged)
cell.accessoryView = swicthView
let itemToRemove = self.items![indexPath.row]
let notifToRemove: String = itemToRemove.notifID!
return cell
}
#objc func switchDidChanged(_ sender: UISwitch){
print("Switch value is \(sender.isOn)")
if(sender.isOn){
print("on")
UIApplication.shared.registerForRemoteNotifications()
}
else{
print("Off")
UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: [notifToRemove])
}
}
}
I believe your code is not working because cells are reused and actions on specific cells should be handled from the cell class rather than from ViewController. Move this code into the UITableViewCell code.
let swicthView = UISwitch(frame: .zero)
swicthView.onTintColor = UIColor (named: "DingerBlue")
swicthView.setOn(true, animated: true)
swicthView.tag = switchViewTag!
swicthView.addTarget(self, action: #selector(self.SwitchBtn(_:)), for: .valueChanged)
#objc func switchDidChanged(_ sender: UISwitch){
print("Switch value is \(sender.isOn)")
if(sender.isOn){
print("on")
UIApplication.shared.registerForRemoteNotifications()
}
else{
print("Off")
UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: [notifToRemove])
}
}
and add a new property in the UITableViewCell
weak var switchViewTag: Int?
Modify your cellForRowAt delegate method to
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//let cell = tableView.dequeueReusableCell(withIdentifier: "itemCell", for: indexPath)
let cell = tableView.dequeueReusableCell(withIdentifier: "itemCell", for: indexPath) as! itemTableViewCell
let item = self.items![indexPath.row]
cell.itemTitle?.text = item.itemName
cell.itemSubTitle?.text = item.itemDescription
cell.switchViewTag = indexPath.row
return cell
}

when i scroll down the tableview the checkmarks of the hidden cells disappear

Cell with enabled checkmark before scrolling:
Cells with disabled checkmarks after I have scrolled up:
hey Guys, I have created a tableview and an add button to add new cells. when i add cells and i enable the UITableViewCell.AccessoryType.checkmark the checkmarks disappear when i scroll the tableview and the cells disappear out of the view.
how can i fix it ?
var waterValue = [String]()
#IBAction func addButtonPressed(_ sender: Any) {
let alert = UIAlertController(title: "add your amount of water for today", message: nil, preferredStyle: .alert)
alert.addTextField(configurationHandler: {(waterAmountTodayTF) in waterAmountTodayTF.placeholder = "enter L for today"})
alert.textFields?.first?.textAlignment = .center
alert.textFields?.first?.becomeFirstResponder()
alert.textFields?.first?.keyboardType = UIKeyboardType.decimalPad
let action = UIAlertAction(title: "add", style: .default) {
(_) in
guard let waterAmountForToday = (alert.textFields?.first?.text) else { return }
self.add("\(waterAmountForToday) L")
// print(self.sliderValue)
}
alert.addAction(action)
present(alert, animated: true)
}
func add(_ individualWaterAmount: String) {
let index = 0
waterValue.insert(individualWaterAmount, at: index)
let indexPath = IndexPath(row: index, section: 0)
tableView.insertRows(at: [indexPath], with: .left)
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 70.0
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return waterValue.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
let individualWaterValues = waterValue[indexPath.row]
cell.textLabel?.text = individualWaterValues
cell.textLabel?.textAlignment = .right
cell.selectionStyle = .none
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if tableView.cellForRow(at: indexPath)?.accessoryType == UITableViewCell.AccessoryType.checkmark {
tableView.cellForRow(at: indexPath)?.accessoryType = UITableViewCell.AccessoryType.none
} else {
tableView.cellForRow(at: indexPath)?.accessoryType = UITableViewCell.AccessoryType.checkmark
}
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
guard editingStyle == .delete else { return }
waterValue.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .automatic)
}
You have not added logic to set accessory type to checkmark while creating new cell.
What you need to do is, save the value which you have selected, and then use that values while creating new cell.
var selectedIndexes: [Int] = []; //global variable
...
...
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
let individualWaterValues = waterValue[indexPath.row]
cell.textLabel?.text = individualWaterValues
cell.textLabel?.textAlignment = .right
cell.accessoryType = selectedIndexes.contains(indexPath.row) ? UITableViewCell.AccessoryType.checkmark : UITableViewCell.AccessoryType.none
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if tableView.cellForRow(at: indexPath)?.accessoryType == UITableViewCell.AccessoryType.checkmark {
tableView.cellForRow(at: indexPath)?.accessoryType = UITableViewCell.AccessoryType.none
selectedIndexes.removeAll(where: { $0 == indexPath.row } )
} else {
tableView.cellForRow(at: indexPath)?.accessoryType = UITableViewCell.AccessoryType.checkmark
selectedIndexes.append(indexPath.row)
}
}

Cell does not get deselected while scrolled back

I have a weird problem. While I select a cell with changing the background color of one UIView component, then I scroll down and selected cell going to be out of bounds of the view. I do select new cell -> previous one should get unselected, but it does not. Because when I back I do have 2 selected cells.
var lastSelectedAtIndexPath: IndexPath?
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
switch tableView {
case myTableView:
if let cell = myTableView.cellForRow(at: indexPath) as? MyTableViewCell {
cell.checkMarkBorder.backgroundColor = UIColor.darkGreyFts
lastSelectedFuelAtIndexPath = indexPath
}
default:
break
}
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
switch tableView {
case myTableView:
if let cell = fuelTableView.cellForRow(at: indexPath) as? MyTableViewCell {
cell.checkMarkBorder.backgroundColor = UIColor.white
}
default:
break
}
}
And iside cellForRowAt I have :
let cell = myTableView.dequeueReusableCell(withIdentifier: "myCell") as! MyTableViewCell
if let lastIndexPath = lastSelectedFuelAtIndexPath {
myTableView.deselectRow(at: lastIndexPath, animated: true)
}
cell.myImage.image = UIImage(named: fuelType)?.withRenderingMode(.alwaysTemplate)
cell.myNameLabel.text = "Test"
Any ideas what is going on?
Thanks in advance!
Don't make changes on cell outside cellForRowAt always change your dataSource and use dataSource in cellForRowAt then in didSelectRowAt and didDeSelectRowAt reload the row.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = myTableView.dequeueReusableCell(withIdentifier: "myCell") as! MyTableViewCell
cell.myImage.image = UIImage(named: fuelType)?.withRenderingMode(.alwaysTemplate)
cell.myNameLabel.text = "Test"
cell.checkMarkBorder.backgroundColor = lastSelectedFuelAtIndexPath == indexPath ? UIColor.darkGreyFts : UIColor.white
return cell
}
Now in didSelectRowAt and didDeSelectRowAt update the lastSelectedFuelAtIndexPath reload the row.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if tableView == myTableView {
lastSelectedFuelAtIndexPath = indexPath
myTableView.reloadRows(at: [indexPath], with: .automatic)
}
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
if tableView == myTableView {
lastSelectedFuelAtIndexPath = nil
myTableView.reloadRows(at: [indexPath], with: .automatic)
}
}