I'm trying to make a filter. I got a tableview. When I click any section, it expands and collapses.
My problem is that when I open and close other sections after clicking on the checkboxes, unselected checkboxes in other sections appear as selected and selected ones are unselected. What should I do? Can you show me some code? Thanks!
https://ibb.co/0htP7Hz // Filter image
var hiddenSections = Set<Int>()
var filtersArray = Set<String>()
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "FilterCell", for: indexPath) as? FilterTableViewCell else
{
fatalError("Product Group Cell not found")
}
guard let item = self.filterElementListVM.itemfilterviewmodelAtIndex(indexPath) else {
return UITableViewCell()
}
cell.setupCell(title: item.definition ?? "", buttonTag: item.id ?? 0, filterArray: self.filtersArray)
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) as? FilterTableViewCell {
let selectedFilterItem = self.filterElementListVM.itemfilterviewmodelAtIndex(indexPath)
if cell.buttonCheck.isSelected {
self.filtersArray.remove(String(selectedFilterItem?.definition ?? ""))
} else {
self.filtersArray.insert(String(selectedFilterItem?.definition ?? ""))
}
cell.buttonCheckTap()
}
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let viewHeader = UIView.init(frame: CGRect.init(x: 0.0, y: 0.0, width: tableView.frame.size.width, height: 67.0))
viewHeader.backgroundColor = .white
let filterVM : FilterViewModel = self.filterElementListVM.filterViewModelAtIndex(section)
let viewFilterHeader : ViewFilter = ViewFilter.init(title: filterVM.definition,
rightImage: UIImage.init(named: "arrow_down")!, isPropertiesChanged: false, isArrowHidden: false)
viewFilterHeader.tag = section
let tap = UITapGestureRecognizer(target: self, action: #selector(hideSection(_:)))
viewFilterHeader.addGestureRecognizer(tap)
viewHeader.addSubview(viewFilterHeader)
viewFilterHeader.snp.makeConstraints { (make) in
make.top.equalTo(7.0)
make.bottom.equalTo(0.0)
make.leading.trailing.equalTo(0)
}
return viewHeader
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 67.0
}
#objc private func hideSection(_ sender: UITapGestureRecognizer? = nil) {
guard let section = sender?.view?.tag else { return }
func indexPathsForSection() -> [IndexPath] {
var indexPaths = [IndexPath]()
for row in 0..<self.filterElementListVM.numberOfRowsInSection(section) {
indexPaths.append(IndexPath(row: row,
section: section))
}
return indexPaths
}
if self.hiddenSections.contains(section) {
self.hiddenSections.remove(section)
self.tableviewFilter.insertRows(at: indexPathsForSection(),
with: .fade)
} else {
self.hiddenSections.insert(section)
self.tableviewFilter.deleteRows(at: indexPathsForSection(),
with: .fade)
}
}
Looks like your configuration works wrong and when you toggle your cell old data applied to your cell. So you need to clear all your data in prepareFroReuse() method inside your UIColelctionViewCell class
More information: https://developer.apple.com/documentation/uikit/uitableviewcell/1623223-prepareforreuse
Related
I try to hide or start the indexPath.row at 1. how can i achieved that ?. I already reversed the indexPath and make the count on numberOfRowsInSection - 1, So the list start from the buttom, but when i clicked on the list the content still not changed according to the reversed indexPath.row
Here is my code
extension PaymentMethodViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return paymentMethod.count
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let data = paymentMethod[indexPath.row]
switch indexPath {
case indexPathForSelected:
guard let cell = tableView.dequeueReusableCell(withIdentifier: ConstantsIdentifier.paymentMethodCellId,
for: indexPath) as? PaymentMethodCell else {
return UITableViewCell()
}
cell.layoutIfNeeded()
cell.setNeedsLayout()
cell.paymentLbl.text = data.paymentGroupTitle
cell.subLbl.text = selectedPayment.title
cell.descriptionLabel.text = selectedPayment.description
cell.phoneNumberTextField.addTarget(self, action: #selector(textFieldDidChange(sender:)), for: .editingChanged)
cell.phoneNumberTextField.isHidden = selectedPayment.title == ConstantsText.titleOVO ? false : true
cell.phoneNumberTextField.textContentType = .telephoneNumber
cell.phoneNumberTextField.keyboardType = .phonePad
cell.phoneNumberTextField.delegate = self
selectedPayment.code == ConstantsPaymentMethod.defaultPaymentCode ? cell.withSeparator() : cell.removeSeparator()
cell.rightIcon.image = selectedPayment.code == ConstantsPaymentMethod.defaultPaymentCode ? UIImage(named: ConstantsImage.ovalTick) : UIImage(named: ConstantsImage.arrowRight)
cell.rightIcon.contentMode = .scaleAspectFit
if selectedPayment.code == ConstantsPaymentMethod.defaultPaymentCode {
hideCellDesc(cell, true)
} else {
hideCellDesc(cell, false)
}
let imageUrl = URL(string: selectedPayment.logo?.lowres ?? "")
if let objectPayment = paramCheckout?["payment"] as? NSDictionary, let ccNumber = objectPayment["cardNumber"] as? String, !ccNumber.isEmpty {
cell.paymentImg.image = UIImage(named: getImageCC(ccName: getTypeCreditCard(ccNumber: ccInfo?.ccNumber ?? "")))
} else {
cell.paymentImg?.sd_setImage(with: imageUrl, placeholderImage: UIImage(named: ConstantsImage.placeholder), options: .highPriority, completed: nil)
}
return cell
default:
let cell:UITableViewCell = tableView.dequeueReusableCell(withIdentifier: ConstantsIdentifier.defaultIndentifier, for: indexPath)
cell.textLabel?.text = data.paymentGroupTitle
cell.textLabel?.numberOfLines = 2
cell.textLabel?.font = UIFont.karlaRegular
let image = UIImageView(image: UIImage(named: ConstantsImage.arrowRight))
cell.accessoryView = image
cell.selectionStyle = .none
return cell
}
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPathForSelected == indexPath && selectedPayment.title == ConstantsText.titleOVO {
return Constant.SelectedHeight + 30
}
if indexPathForSelected == indexPath && selectedPayment.code == ConstantsPaymentMethod.creditCard {
return Constant.CellHeight
}
return indexPathForSelected == indexPath ? Constant.SelectedHeight + 30 : Constant.CellHeight
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return Constant.HeaderHeight
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return ConstantsText.titlePaymentMethod
}
func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
view.tintColor = UIColor.white
let header = view as! UITableViewHeaderFooterView
header.textLabel?.font = UIFont.karlaBold
header.textLabel?.textColor = UIColor.mainBlue
}
}
Please help me, Thanks
Firstly add UITableViewDelegate, I think this is the problem:
extension PaymentMethodViewController: UITableViewDataSource, UITableViewDelegate {}
and
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
}
there is a table view and i create a button in Second cell . i handled Button Touch event with protocol .i want to add a empty text field in new row at current section Exactly below of phone number text field when add button touched but i cant handle it .
table view cell :
protocol InsertTableCellDelegate {
func insertTableCellDelegate_addrowbtn(sender:InsertTableCell1)
}
class InsertTableCell1: UITableViewCell {
var delegate : InsertTableCellDelegate?
#IBOutlet weak var tbCreateRow: UITableView!
#IBOutlet weak var txtPhoneNumber: JVFloatLabeledTextField!
override func awakeFromNib() {
super.awakeFromNib()
}
#IBAction func btn_Add_DidTouch(_ sender: Any) {
if let delegate = self.delegate
{
delegate.insertTableCellDelegate_addrowbtn(sender: self)
}
}
}
table view Delegates :
func numberOfSections(in tableView: UITableView) -> Int {
return 3
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell0 = tableView.dequeueReusableCell(withIdentifier: "InsertTableCell0") as! InsertTableCell0
return cell0
}else if indexPath.section == 1 {
//this section should handle add textfield in new row when text button touhed
let cell1 = tableView.dequeueReusableCell(withIdentifier: "InsertTableCell1") as! InsertTableCell1
cell1.delegate = self
return cell1
}else {
let cell2 = tableView.dequeueReusableCell(withIdentifier: "InsertTableCell2") as! InsertTableCell2
cell2.txtEmail.text = strEditEmail
return cell2
}
}
//protocol of button :
func insertTableCellDelegate_addrowbtn(sender: InsertTableCell1) {
print("touched")
}
numberOfRowsInSection have fixed number of cell. First you need to create a
dynamic dataSource.
sample code :
var dataSource : [Int] = Array.init(repeating: 1, count: 3)
func numberOfSections(in tableView: UITableView) -> Int {
return dataSource.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataSource[section]
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell0 = tableView.dequeueReusableCell(withIdentifier: "InsertTableCell0") as! InsertTableCell0
return cell0
}else if indexPath.section == 1 {
//this section should handle add textfield in new row when text button touhed
let cell1 = tableView.dequeueReusableCell(withIdentifier: "InsertTableCell1") as! InsertTableCell1
cell1.delegate = self
return cell1
}else {
let cell2 = tableView.dequeueReusableCell(withIdentifier: "InsertTableCell2") as! InsertTableCell2
cell2.txtEmail.text = strEditEmail
return cell2
}
}
//protocol of button :
func insertTableCellDelegate_addrowbtn(sender: InsertTableCell1) {
dataSource[1] = dataSource[1] + 1
tableView.reloadData() // or you can use beginUpdates() and endUpdates()
}
Sample of code for add new Row when click on add button in Section
//Create outlet for table view
#IBOutlet weak var currentInsetTableView: UITableView!
//Declare these variable
let reuseInsetCellIdentifier = "insertCell";
let titleSection = ["Add Phone", "Add Email"]
var arrayForCellInSection = Array<Any>()
//Add this code in viewDidLoad()
currentInsetTableView.delegate = self
currentInsetTableView.dataSource = self
currentInsetTableView.estimatedRowHeight = 200
currentInsetTableView.rowHeight = UITableView.automaticDimension
currentInsetTableView.register(UINib(nibName: "CurrentInsertTableViewCell", bundle: nil), forCellReuseIdentifier: reuseInsetCellIdentifier)
arrayForCellInSection = Array.init(repeating: 1, count: titleSection.count)
//Implematation of UITablewView Delegate
func numberOfSections(in tableView: UITableView) -> Int {
return titleSection.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arrayForCellInSection[section] as! Int
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: reuseInsetCellIdentifier, for: indexPath)
as! CurrentInsertTableViewCell
cell.backgroundColor = UIColor.black
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 50
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = UIView.init(frame: CGRect.init(x: 0, y: 0, width: tableView.frame.width, height: 50))
headerView.backgroundColor = UIColor.black
let buttonX = 10
let buttonY = 10
let buttonWidth = 30
let buttonHeight = 30
let button = UIButton(type: .system)
let imgAdd = UIImage(named: "Add")
button.setImage(imgAdd, for: .normal)
button.addTarget(self, action: #selector(buttonClickedForInsertRowInSection(sender:)), for: .touchUpInside)
button.frame = CGRect(x: buttonX, y: buttonY, width: buttonWidth, height: buttonHeight)
button.tag = section
headerView.addSubview(button)
let label = UILabel()
label.frame = CGRect.init(x: button.frame.size.width + CGFloat((2 * buttonX)), y: CGFloat(buttonY), width: headerView.frame.width - button.frame.size.width + CGFloat((3 * buttonX)), height: headerView.frame.height - CGFloat((2 * buttonY)))
label.text = titleSection[section]
label.textColor = UIColor.white
headerView.addSubview(label)
return headerView
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 50
}
//CurrentInsertTableViewCell Desing
//Final Result: When we press two times on first section add button & one times on second section add button
I have a tableview with 3 collapsible sections. users can only select rows in section 3 and when they select it goes green. However, when this section is collapsed all the selections are forgotten and when I re-open the section, usually the first row is always green (though it shouldn't be). Sometimes, other sections end up being green too when they shouldn't - not sure what I've got wrong?
// Number of table sections
func numberOfSections(in tableView: UITableView) -> Int {
return 3
}
// Set the number of rows
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if (self.expandedSectionHeaderNumber == section) {
// If markscheme, create the markscheme format
if (section == 2)
{
return self.markschemeRows.count
}
else
{
let arrayOfItems = self.sectionItems[section] as! NSArray
return arrayOfItems.count
}
} else {
return 0;
}
}
// Set titles for sections
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if (self.sectionNames.count != 0) {
return self.sectionNames[section] as? String
}
return ""
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 44.0;
}
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat{
return 0;
}
func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
//recast your view as a UITableViewHeaderFooterView
let header: UITableViewHeaderFooterView = view as! UITableViewHeaderFooterView
header.contentView.backgroundColor = UIColor.darkGray
header.textLabel?.textColor = UIColor.white
if let viewWithTag = self.view.viewWithTag(kHeaderSectionTag + section) {
viewWithTag.removeFromSuperview()
}
let headerFrame = self.view.frame.size
let theImageView = UIImageView(frame: CGRect(x: headerFrame.width - 32, y: 13, width: 18, height: 18));
theImageView.image = UIImage(named: "Chevron-Dn-Wht")
theImageView.tag = kHeaderSectionTag + section
header.addSubview(theImageView)
// make headers touchable
header.tag = section
let headerTapGesture = UITapGestureRecognizer()
headerTapGesture.addTarget(self, action: #selector(CaseViewController.sectionHeaderWasTouched(_:)))
header.addGestureRecognizer(headerTapGesture)
}
// Load the table data
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath) as! CustomTableCell
let section = self.sectionItems[indexPath.section] as! NSArray
cell.textLabel?.textColor = UIColor.black
cell.selectionStyle = .none
//cell.backgroundColor = .white
// Get the data from different arrays depending on the section
if indexPath.section == 2 {
cell.textData?.text = markschemeRows[indexPath.row]
} else {
cell.textData?.text = section[indexPath.row] as! String
}
return cell
}
func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
if indexPath.section == 0{
if indexPath.row == 0{
return nil
}
}
else if indexPath.section == 1{
if indexPath.row == 0{
return nil
}
}
return indexPath
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.selectRow(at: indexPath, animated: true, scrollPosition: .none)
let cell = tableView.cellForRow(at: indexPath)
cell?.backgroundColor = .green
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
let cell = tableView.cellForRow(at: indexPath)
if (cell?.backgroundColor == .green)
{
cell?.backgroundColor = .white
}
}
// MARK: - Expand / Collapse Methods
#objc func sectionHeaderWasTouched(_ sender: UITapGestureRecognizer) {
let headerView = sender.view as! UITableViewHeaderFooterView
let section = headerView.tag
let eImageView = headerView.viewWithTag(kHeaderSectionTag + section) as? UIImageView
if (self.expandedSectionHeaderNumber == -1) {
self.expandedSectionHeaderNumber = section
tableViewExpandSection(section, imageView: eImageView!)
} else {
if (self.expandedSectionHeaderNumber == section) {
tableViewCollapeSection(section, imageView: eImageView!)
} else {
let cImageView = self.view.viewWithTag(kHeaderSectionTag + self.expandedSectionHeaderNumber) as? UIImageView
tableViewCollapeSection(self.expandedSectionHeaderNumber, imageView: cImageView!)
tableViewExpandSection(section, imageView: eImageView!)
}
}
}
func tableViewCollapeSection(_ section: Int, imageView: UIImageView) {
let sectionData = self.sectionItems[section] as! NSArray
self.expandedSectionHeaderNumber = -1;
if (sectionData.count == 0) {
return;
} else {
UIView.animate(withDuration: 0.4, animations: {
imageView.transform = CGAffineTransform(rotationAngle: (0.0 * CGFloat(Double.pi)) / 180.0)
})
var indexesPath = [IndexPath]()
// If markscheme, different number needed
if (section == 2)
{
for i in 0 ..< markschemeRows.count {
let index = IndexPath(row: i, section: section)
indexesPath.append(index)
}
}
else
{
for i in 0 ..< sectionData.count {
let index = IndexPath(row: i, section: section)
indexesPath.append(index)
}
}
self.tableView!.beginUpdates()
self.tableView!.deleteRows(at: indexesPath, with: UITableView.RowAnimation.fade)
self.tableView!.endUpdates()
}
}
func tableViewExpandSection(_ section: Int, imageView: UIImageView) {
let sectionData = self.sectionItems[section] as! NSArray
if (sectionData.count == 0) {
self.expandedSectionHeaderNumber = -1;
return;
} else {
UIView.animate(withDuration: 0.4, animations: {
imageView.transform = CGAffineTransform(rotationAngle: (180.0 * CGFloat(Double.pi)) / 180.0)
})
var indexesPath = [IndexPath]()
// If markscheme, create the markscheme format
if (section == 2)
{
for i in 0 ..< markschemeRows.count {
let index = IndexPath(row: i, section: section)
indexesPath.append(index)
}
}
else
{
for i in 0 ..< sectionData.count {
let index = IndexPath(row: i, section: section)
indexesPath.append(index)
}
}
self.expandedSectionHeaderNumber = section
self.tableView!.beginUpdates()
self.tableView!.insertRows(at: indexesPath, with: UITableView.RowAnimation.fade)
self.tableView!.endUpdates()
}
}
The key thing to understand here is that the Cells are Reused when you say
let cell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath) as! CustomTableCell
dequeueReusableCell basically reuses a previously loaded UITableViewCell and in your case you changed the background color of the cell to green
To get a better understanding of the concept consider reading some articles like this one on Reusing Cells
Changes in Code
What you should do considering the above in mind
var backgroundColors = [UIColor](repeating: UIColor.white, count: 10)
you have to save the state of the colors in a model (ideally you should make a custom struct)
now in cellForRowAt add this
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath) as! CustomTableCell
.
.
cell.backgroundColor = backgroundColors[indexPath.row]
// **EDIT**
let cellShouldBeSelected = backgroundColors[indexPath.row] == .green
if cellShouldBeSelected {
tableView.selectRow(at: indexPath, animated: false, scrollPosition: .none)
}
.
.
return cell
}
And your didSelectRowAt and didDeselectRowAt should update the model
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.backgroundColors[indexPath.row] = .green
tableView.reloadRows(at: [indexPath], with: .none)
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
if (self.backgroundColors[indexPath.row] == .green) {
self.backgroundColors[indexPath.row] = .white
tableView.reloadRows(at: [indexPath], with: .none)
}
}
On second thought
Solution 2 (Recommended)
From you comments, i see you only need one selected cell at one time, assuming that keeping an array of backgroundColors is just a bad idea.
declare a int for the selected index
// -1 representing nothing is selected in the beginning
var selectedRow = -1
now your cellForRowAt will look like
let cell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath) as! CustomTableCell
.
.
if indexPath.section == 2, indexPath.row == self.selectedRow {
cell.backgroundColor = .green
} else {
cell.backgroundColor = .white
}
.
.
return cell
}
And your didSelectRowAt
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.section == 2 {
self.selectedRow = indexPath.row
tableView.reloadSections([2], with: .automatic)
}
}
And now you can remove didDeselectRowAt completely
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arraylist.count
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 50.0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = PopupCellTableViewCell()
cell = (tableView.dequeueReusableCell(withIdentifier: "advnccell", for: indexPath) as? PopupCellTableViewCell)!
cell.bgView = Utilities().viewborder(vw: cell.bgView )
let dict = arraylist[indexPath.row] as! NSDictionary
let cd = dict.value(forKey: "Code") as? String ?? ""
let desc = dict.value(forKey: "Description") as? String ?? ""
cell.tittleLbl.text = cd + " - " + desc
if selectedRows.contains(indexPath)
{
cell.checkBtn.setImage(UIImage(named:"check"), for: .normal)
}
else
{
cell.checkBtn.setImage(UIImage(named:"uncheck"), for: .normal)
}
if (cell.checkBtn.currentImage?.isEqual(UIImage(named: "check")))!
{
UserDefaults.standard.set(cell.tittleLbl.text, forKey: "tittle")
}
cell.btnAction.tag = indexPath.row
cell.btnAction.addTarget(self, action: #selector(checkBoxSelection(_:)), for: .touchUpInside)
return cell
}
// checkbox selection
#objc func checkBoxSelection(_ sender:UIButton)
{
let selectedIndexPath = IndexPath(row: sender.tag, section: 0)
if self.selectedRows.contains(selectedIndexPath)
{
self.selectedRows.remove(at: self.selectedRows.index(of: selectedIndexPath)!)
}
else
{
self.selectedRows.append(selectedIndexPath)
}
self.tableVw.reloadData()
}
At present i am getting only one value, how can i get if i selected multiple check buttons
Fix this portion of your code:
if selectedRows.contains(indexPath)
{
cell.checkBtn.setImage(UIImage(named:"check"), for: .normal)
UserDefaults.standard.set(cell.tittleLbl.text, forKey: "tittle")
}
else
{
cell.checkBtn.setImage(UIImage(named:"uncheck"), for: .normal)
}
Good time of day, in my app i have a tableview and custom cell, in cell there are labels, button and progressBar, so that when i tap button download proceeds and progressBar shows progress, but when i scroll down i realise that there are other cells are selected and shows progress and when i scroll up again progress of my selected cell stops. Could you help, any feedbacks appreciated )
That's my TableViewController :
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return titles.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! ViewControllerTableViewCell
cell.pesnya.text = titles[indexPath.row]
cell.pevets.text = artists[indexPath.row]
cell.url = urls[indexPath.row]
return (cell)
}
#IBAction func buttonPressed(_ sender: AnyObject) {
(sender as! UIButton).isSelected = !(sender as! UIButton).isSelected
if (sender as! UIButton).isSelected {
if let indexPath = tableView.indexPath(for: sender.superview!?.superview as! UITableViewCell) {
DownloadManager.shared.download(url: urls[indexPath.row], title: titles[indexPath.row])
}
} else {
// (sender as! UIButton).setTitle("Удалить", for: UIControlState.normal)
if let indexPath = tableView.indexPath(for: sender.superview!?.superview as! UITableViewCell) {
let name = "\(titles[indexPath.row]).mp3"
let name2 = name.replacingOccurrences(of: " ", with: "")
let filePathURL = URL(string:"string")
do {
try FileManager.default.removeItem(at: filePathURL!)
} catch {
print("Could not delete file: \(error)")
}
}
}
}
This is because table view cell will be reused when you scroll. Set views to initial status in cell's prepareForReuse. Like this:
class ACell: UITableViewCell {
override func prepareForReuse() {
view.hidden = true
}
}
try this :-
override func tableView(_ tableView: UITableView, numberOfRowsInSection
section: Int) -> Int
{
return titles.count
}
override func tableView(_ tableView: UITableView, cellForRowAt
indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for:
indexPath) as! ViewControllerTableViewCell
cell.pesnya.text = titles[indexPath.row]
cell.pevets.text = artists[indexPath.row]
cell.url = urls[indexPath.row]
// Create IBOutlet for button
cell.btnPressed.tag = indexPath.row
cell.btnPressed.addTarget(self, action: #selector(self.buttonPressed(sender:)), for: .touchUpInside)
if cell.btnPressed.isSelected {
DownloadManager.shared.download(url: urls[indexPath.row], title: titles[indexPath.row])
}else {
let name = "\(titles[indexPath.row]).mp3"
let name2 = name.replacingOccurrences(of: " ", with: "")
let filePathURL = URL(string:"string")
do {
try FileManager.default.removeItem(at: filePathURL!)
} catch {
print("Could not delete file: \(error)")
}
}
return (cell)
}
#IBAction func buttonPressed(_ sender: UIButton) {
let indexPath = IndexPath(row: sender.tag, section: 0)
if let cell = tableView.cellForRow(at: indexPath) as?
ViewControllerTableViewCell {
cell.btnPressed.isSelected = !cell.btnPressed.isSelected
tableview.reloadData()
}
}