I’m working on an iOS project and I’m facing an issue with my UITableView
. I can’t prevent the table view from refreshing cell data when scrolling down. I use Core Data to manage and fetch my data.
In the table view, each cell has a (+) button to add an item. Tapping this button also changes the color of the cell. However, when I scroll down, the cells refresh and their states reset, which means the color change and other dynamic states are lost.
AddShoppingItemTableViewCell:
import UIKit
// MARK: - PantryTableViewCellDelegate
protocol AddShoppingItemTableViewCellDelegate: AnyObject {
func addButtonTapped(shoppingSubItem: Shopping_Sub_List)
func editButtonTapped(shoppingSubItem: Shopping_Sub_List)
}
class AddShoppingItemTableViewCell: UITableViewCell {
@IBOutlet weak var addToListButton: UIButton!
@IBOutlet weak var itemNameLabel: UILabel!
@IBOutlet weak var categoryLabel: UILabel!
@IBOutlet weak var editButton: UIButton!
weak var delegate: AddShoppingItemTableViewCellDelegate?
var shoppingSubItem: Shopping_Sub_List?
override func awakeFromNib() {
super.awakeFromNib()
itemNameLabel.font = UIFont(name: Global.Inter_Medium_500, size: 17.0)
categoryLabel.font = UIFont(name: Global.Inter_Medium_500, size: 17.0)
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
// MARK: - Action
// add To List Button Action
@IBAction func addToListButtonAction(_ sender: UIButton) {
guard let shoppingSubItem = shoppingSubItem else { return }
addToListButton.setImage(UIImage(named: "Added"), for: .normal)
delegate?.addButtonTapped(shoppingSubItem: shoppingSubItem)
}
// edit Button Action
@IBAction func editButtonAction(_ sender: UIButton) {
guard let shoppingSubItem = shoppingSubItem else { return }
delegate?.editButtonTapped(shoppingSubItem: shoppingSubItem)
}
// MARK: Cell Configuration
// configurate The Cell
func configurateTheCell(_ shoppingSubList: Shopping_Sub_List) {
self.shoppingSubItem = shoppingSubList
itemNameLabel.text = shoppingSubList.name
categoryLabel.text = "in (shoppingSubList.category ?? "Uncategorized")"
}
}
AddShoppingItemsVC:
import UIKit
import CoreData
class AddShoppingItemsVC: UIViewController {
// MARK: - IBOutlet
@IBOutlet weak var addItemSearchBar: UISearchBar!
@IBOutlet weak var microphoneButton: UIButton!
@IBOutlet weak var addShoppingItemTableView: UITableView!
var shoppingList: Shopping_List?
let coreDataHelper = CoreDataHelper()
var allShoppingSubLists: [Shopping_Sub_List]?
var filteredShoppingSubLists: [Shopping_Sub_List]?
override func viewDidLoad() {
super.viewDidLoad()
addItemSearchBar.delegate = self
addShoppingItemTableView.delegate = self
addShoppingItemTableView.dataSource = self
addShoppingItemTableView.register(UINib(nibName: "AddShoppingItemTableViewCell", bundle: nil),
forCellReuseIdentifier: Global.AddShoppingItemTableViewCellIdentifier)
addShoppingItemTableView.register(UINib(nibName: "AddItemTableViewCell", bundle: nil),
forCellReuseIdentifier: Global.AddItemTableViewCellIdentifier)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.isNavigationBarHidden = false
self.navigationController?.navigationBar.prefersLargeTitles = false
fetchAllShoppingSubLists()
addItemSearchBar.text = ""
addShoppingItemTableView.reloadData()
}
// MARK: - Function
// Function to fetch all shopping sub-lists
func fetchAllShoppingSubLists() {
if let shoppingSubLists = coreDataHelper.fetchAllShoppingSubListData() {
self.allShoppingSubLists = shoppingSubLists.sorted { $0.name ?? "" < $1.name ?? "" }
self.filteredShoppingSubLists = shoppingSubLists.sorted { $0.name ?? "" < $1.name ?? "" }
} else {
print("Error fetching shopping sub-lists")
}
}
// MARK: - Action
// microphone Button Action
@IBAction func microphoneButtonAction(_ sender: UIButton) {
print("microphoneButtonAction")
}
}
extension AddShoppingItemsVC: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return (filteredShoppingSubLists?.count ?? 0) + 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == (filteredShoppingSubLists?.count ?? 0) {
// This is the last cell
if let cell = tableView.dequeueReusableCell(withIdentifier: Global.AddItemTableViewCellIdentifier,
for: indexPath) as? AddItemTableViewCell {
cell.delegate = self
return cell
}
} else {
// Regular cells for shopping sub lists
if let cell = tableView.dequeueReusableCell(withIdentifier: Global.AddShoppingItemTableViewCellIdentifier,
for: indexPath) as? AddShoppingItemTableViewCell {
guard let shoppingSubLists = filteredShoppingSubLists?[indexPath.row] else { return cell}
cell.configurateTheCell(shoppingSubLists)
cell.delegate = self
return cell
}
}
return UITableViewCell()
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 56
}
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let editAction = UIContextualAction(style: .normal, title: "Remove") { [weak self] (_, _, completionHandler) in
self?.deleteActionForRow(at: indexPath)
completionHandler(true)
}
editAction.backgroundColor = UIColor(named: "DeleteAction")
return UISwipeActionsConfiguration(actions: [editAction])
}
// edit Action For Row
private func deleteActionForRow(at indexPath: IndexPath) {
print(indexPath)
}
}
// MARK: - AddShoppingItemTableViewCellDelegate
extension AddShoppingItemsVC: AddShoppingItemTableViewCellDelegate {
func editButtonTapped(shoppingSubItem: Shopping_Sub_List) {
let vc = storyboard?.instantiateViewController(identifier: Global.EditItemViewControllerIdentifier) as! EditItemViewController
vc.selectedShoppingSubList = shoppingSubItem
vc.parentList = shoppingList
vc.isSavaItem = false
self.navigationController?.pushViewController(vc, animated: true)
}
func addButtonTapped(shoppingSubItem: Shopping_Sub_List) {
guard let shoppingLists = shoppingList else { return }
coreDataHelper.addShoppingSubListToItemsList(subList: shoppingSubItem, parentList: shoppingLists)
}
}
// MARK: - UISearchBarDelegate
extension AddShoppingItemsVC: UISearchBarDelegate {
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
if searchText.isEmpty {
filteredShoppingSubLists = allShoppingSubLists
} else {
filteredShoppingSubLists = allShoppingSubLists?.filter { $0.name?.lowercased().contains(searchText.lowercased()) ?? false }
}
addShoppingItemTableView.reloadData()
}
}
// MARK: - AddItemTableViewCellDelegate
extension AddShoppingItemsVC: AddItemTableViewCellDelegate {
func addButtonTapped() {
let vc = storyboard?.instantiateViewController(identifier: Global.EditItemViewControllerIdentifier) as! EditItemViewController
vc.isSavaItem = true
self.navigationController?.pushViewController(vc, animated: true)
}
}
I can’t prevent UITableView
from refreshing cell data when scrolling down. I use Core Data to fetch and display all shopping lists (names). When I tap the addButtonTapped
, all cells have a (+) button to add an item. Tapping this button also changes the color of the cell. However, when I scroll down, the cells refresh automatically. I want to stop this from happening.