0

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()
}
9
  • Just override your WeatherCell prepareForReuse method and set those values there and reload Commented Mar 25 at 1:45
  • Hay @LeoDabus, how would I do that, sorry I'm a bit unfamiliar with doing that? would you like me to add any further information to help with explaining that? 😅 Commented Mar 25 at 1:50
  • Well I am not sure it this is your issue but you should always make sure to erase the cell contents before reusing them. If your issue is just updating your cell contents just reload them after getting the new data. Commented Mar 25 at 4:49
  • my question is how do I do that. how do I "reload them after getting the new data." is there like a "tableview.resetalldata()" function? I saw "TableViewForUpcomingWeatherForecast.reloadData()" but that did nothing at all. Commented Mar 25 at 13:28
  • Yes that’s how you reload all cells. You can also just reload a specific cell if you need. Print your data source before reloading and check if the content is already fetched. Bte don’t use UserDefaults to store your app data. It should only be used to store its settings Commented Mar 25 at 15:42

2 Answers 2

0

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.

Sign up to request clarification or add additional context in comments.

8 Comments

Thanks for commenting! However this is a little too "codey" for me, I tried implementing it and getting quite a bit of errors. 😅 The thing to note is that my current code actually works fine. The user default values save perfectly but once they are updated then I need the cells to reset to highlight the new string values. When I leave the page and reopen it, the new values are there in the cells because the system saved them. I need a way to reset. That's really all I'm looking for here like the [hypothetical] button I mentioned in the question. Would you be able to help me with that? ☺️
From my perspective, it's how you treat the data, it didn't rely on cell or tableView itself. Let's say, at 1st you have no data, thus tableView is empty. Then users do something -> update data source -> tableView now has a single cell. After this, you leave the controller and reopen it. Now at 2st, you want to clear up the tableView and display empty again. I would consider giving the initial data from outside of 'WeatherFeatures' rather than controlling it internally, and allowing the tableView to render itself - depending on the data source.
Hay! the code actually works and it resets my individual cells, but the issue is it doesn't reset the user defaults data even though I have confirmed that indeed the data has been changed. Can you please help me to fix this?
I don't get it, you also want to reset UserDefaults data when you leave the controller, don't you? If that's the case, why use UserDefaults instead of a class-scoped property?
No I'll explain what I mean. What I want to do is this, when the user default values are updated in the view controller, after that, I want to reset the cells to feature those NEW user default properties. each cell contains a value of the user default variables, Once the User default values are reset, and once the cells are reloaded, then the cells should have the new data within. I don't want to have to leave the view in order to do that. Again I am looking for a solution to show the new data, I only have this and it doesn't reset the values within -
|
0

Okay guys, the issue was that the User Default data was hardcoded. When -

 private lazy var WeatherForecastCells: [WeatherCell] = [
         WeatherCell(image: "", date: date1ForTableView.string(forKey: "Date1")!, low: Int(low1ForTableView.double(forKey: "Low1")), high: Int(high1ForTableView.double(forKey: "High1"))),
           
    ] 

was called, the user default data was already entered. I simply had to move it to my cell data so that it would always be reset when the cells were entered. This was the only edit I made as well as deleting the above line of code and moving it into the cell:

//MARK: - TableViewDataSource
extension WeatherFeatures: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        
        return 1
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "WeatherCellsForWeatherFeature", for: indexPath) as! WeatherForecastTableViewCell
        cell.layer.borderWidth = 1
        cell.layer.borderColor = CGColor(red: 0, green: 0, blue: 0, alpha: 1)
        
     
        
        lazy var WeatherForecastCells: [WeatherCell] = [
            
            WeatherCell(image: "", date: date1ForTableView.string(forKey: "Date1")!, low: Int(low1ForTableView.double(forKey: "Low1")), high: Int(high1ForTableView.double(forKey: "High1"))),
           
        ]

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.