UserDefaults with Struct - TableView not displaying data from saved from UserDefaults?

I am having problem displaying data on the table view cell
These are my code:

struct Person: Codable {
var firstName: String
var lastName: String
}

class viewController: UIViewController {

var newPerson = [Person]()

override func viewDidLoad() {

let person = [Person(firstName: "Peterson", lastName: "Jota") , Person(firstName: "John", lastName: "Paul")]
   
let encoder = JSONEncoder()
 if let encoded = try? encoder.encode(person) {
      UserDefaults.standard.set(encoded, forKey: "savedPerson")
    }
}
}


var person = [Person]()

func tableView( tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return person.count
  }

func tableView(
tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCell(withIdentifier: "cellID", for: indexPath) as! UITableViewCell

  cell.textLabel?.text = person[indexPath.row]
 
return cell
}
Answered by Claude31 in 670442022
The problem is not UserDefaults but errors in your code (formatted with <> tool):

Code Block
struct Person: Codable {
var firstName: String
var lastName: String
}
class viewController: UIViewController {
var newPerson = [Person]()
override func viewDidLoad() {
let person = [Person(firstName: "Peterson", lastName: "Jota") , Person(firstName: "John", lastName: "Paul")]
let encoder = JSONEncoder()
if let encoded = try? encoder.encode(person) {
UserDefaults.standard.set(encoded, forKey: "savedPerson")
}
}
}
var person = [Person]()
func tableView( tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return person.count
}
func tableView( tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellID", for: indexPath) as! UITableViewCell
cell.textLabel?.text = person[indexPath.row]
return cell
}

Line 8, you declare newPerson but never use it. What is it for ?
Line 12, you create person. But it does not exist outside of viewDidLoad.
So line 25, person is empty. Hence return 0. And so, nothing is displayed in TableView.

Some other comments for better readabilty
  • Names of class should start with Uppercase : class ViewController

  • person is an array, better name it persons.

  • Declaration better be at beginning of class.


So, more correct code:
Code Block
struct Person: Codable {
var firstName: String
var lastName: String
}
class ViewController: UIViewController {
var newPerson = [Person]() // <== Where do you use it ?
var persons = [Person]() // renamed
override func viewDidLoad() {
// NOT Redeclare HERE let person = [Person(firstName: "Peterson", lastName: "Jota") , Person(firstName: "John", lastName: "Paul")]
person = [Person(firstName: "Peterson", lastName: "Jota") , Person(firstName: "John", lastName: "Paul")] // Now, array is populated
let encoder = JSONEncoder()
if let encoded = try? encoder.encode(persons) {
UserDefaults.standard.set(encoded, forKey: "savedPerson")
}
}
}
func tableView( tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return persons.count
}
func tableView( tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellID", for: indexPath) as! UITableViewCell
cell.textLabel?.text = persons[indexPath.row]
return cell
}


If that works, don't forget to close the thread. Otherwise tell exactly what the remaining problem is and post more code if needed.
Please show full code. Fragments of code do not make sense.
In which class person, tableView(_:numberOfRowsInSection:) and tableView(_:cellForRowAt:) are defined?
How are you filling data into the property person? (Asking about the property person, not about the local variable person.)

One more, please use the Code block feature (icon <>) when you want to show some codes.
Accepted Answer
The problem is not UserDefaults but errors in your code (formatted with <> tool):

Code Block
struct Person: Codable {
var firstName: String
var lastName: String
}
class viewController: UIViewController {
var newPerson = [Person]()
override func viewDidLoad() {
let person = [Person(firstName: "Peterson", lastName: "Jota") , Person(firstName: "John", lastName: "Paul")]
let encoder = JSONEncoder()
if let encoded = try? encoder.encode(person) {
UserDefaults.standard.set(encoded, forKey: "savedPerson")
}
}
}
var person = [Person]()
func tableView( tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return person.count
}
func tableView( tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellID", for: indexPath) as! UITableViewCell
cell.textLabel?.text = person[indexPath.row]
return cell
}

Line 8, you declare newPerson but never use it. What is it for ?
Line 12, you create person. But it does not exist outside of viewDidLoad.
So line 25, person is empty. Hence return 0. And so, nothing is displayed in TableView.

Some other comments for better readabilty
  • Names of class should start with Uppercase : class ViewController

  • person is an array, better name it persons.

  • Declaration better be at beginning of class.


So, more correct code:
Code Block
struct Person: Codable {
var firstName: String
var lastName: String
}
class ViewController: UIViewController {
var newPerson = [Person]() // <== Where do you use it ?
var persons = [Person]() // renamed
override func viewDidLoad() {
// NOT Redeclare HERE let person = [Person(firstName: "Peterson", lastName: "Jota") , Person(firstName: "John", lastName: "Paul")]
person = [Person(firstName: "Peterson", lastName: "Jota") , Person(firstName: "John", lastName: "Paul")] // Now, array is populated
let encoder = JSONEncoder()
if let encoded = try? encoder.encode(persons) {
UserDefaults.standard.set(encoded, forKey: "savedPerson")
}
}
}
func tableView( tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return persons.count
}
func tableView( tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellID", for: indexPath) as! UITableViewCell
cell.textLabel?.text = persons[indexPath.row]
return cell
}


If that works, don't forget to close the thread. Otherwise tell exactly what the remaining problem is and post more code if needed.
Thank you so much. It works
UserDefaults with Struct - TableView not displaying data from saved from UserDefaults?
 
 
Q