swiftuitableviewnsuserdefaults

Unable to reset user default text within a set cell:


This is my code:

class WeatherFeatures: UIViewController, UITextViewDelegate, WeatherManagerDelegate {
    let date1ForTableView = UserDefaults.standard
    let low1ForTableView = UserDefaults.standard
    let high1ForTableView = UserDefaults.standard
    
    ...
    
    private lazy var WeatherForecastCells: [WeatherCell] = [
         WeatherCell(image: "", date: date1ForTableView.string(forKey: "Date1")!, low: Int(low1ForTableView.double(forKey: "Low1")), high: Int(high1ForTableView.double(forKey: "High1"))),
           
    ]
}
        
extension WeatherFeatures: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return WeatherForecastCells.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "WeatherCellsForWeatherFeature", for: indexPath) as! WeatherForecastTableViewCell

        cell.WeatherDetails.text = "\(WeatherForecastCells[indexPath.row].date) - Low: \(WeatherForecastCells[indexPath.row].low) High: \(WeatherForecastCells[indexPath.row].high)"
        
        return cell
    }
}

The line that states "cell.WeatherDetails.text = "\(WeatherForecastCells[indexPath.row].date) - Low: \(WeatherForecastCells[indexPath.row].low) High: \(WeatherForecastCells[indexPath.row].high)"" once the cell is established changes as the user interacts with the interface such as when the user changes the location they want to see the weather of. The data in the user default values changes as this is done.

My question is that is there a UIButton action that resets the cells specifically to factor in the new edits to the user default values? such as for example:

@IBAction func resetMyCells(_ sender: UIButton) {
    tableview.cells.UIView.Reset()
}

Solution

  • You should keep in mind that each cell in cellForRowAt maps 1-1 with WeatherForecastCells data source. And UITableView has a re-use mechanism which means that if you have thoudsands of WeatherForecastCells, it just draws a few cell (visibleCells) and then re-uses them repeatedly when you're scrolling.

    So, no matter what kind of storage you're using, UserDefaults, CoreData, etc, if you want to reload the cell. You need to accomplish 2 things:

    1. Update the data source at a specific indexPath
    //Let's say you have 5 elements within `WeatherForecastCells` and you want to update the second element
    private func updateDataSource(_ data: String, at indexPath: IndexPath) {
        guard let WeatherForecastCells.count > indexPath.row else { return }
        WeatherForecastCells[indexPath.row].low = data
        ...
    }
    
    updateDataSource("high", .init(row: 2, section: 0))
    
    1. Reload the cell that belongs to this data source
    tableView.reloadRows(at: .init(row: 2, section: 0), with: .none)
    

    And then, whenver cellForRowAt from UITableViewDataSource get called, it will dequeue (re-use) the cell and then bind the desired data at the proper indexPath.

    Notice: In the case you have a if else condition within tableView:cellForRowAtIndexPath:, always fill both if and else to avoid unexpected behavior while re-using.