corasan
corasan

Reputation: 2754

iOS TableView custom cell not showing anything

I'm new to iOS and Swift and I'm trying to learn a little by creating a simple Todo app. The problem I came across is that no matter how I implement the code (followed multiple tutorials) and storyboards, the data doesn't show and the custom cells is not customized (it looks exactly how the default cells look even though I've customized it). I already connected my delegate and dataSource

Edit: I already assigned the reuse identifier

TodosView.swift

import UIKit

class TodosView: UIViewController {
    @IBOutlet weak var todosTable: UITableView!

    var todos: [Todo] = []

    override func viewDidLoad() {
        super.viewDidLoad()
        todosTable.delegate = self
        todosTable.dataSource = self

        self.addTodo()
    }

    func addTodo() {
        let todo1 = Todo(text: "My first todo")
        let todo2 = Todo(text: "My second todo")

        todos = [todo1, todo2]
    }
}

extension TodosView: UITableViewDelegate, UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return todos.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let todo = todos[indexPath.row]
        let cell = tableView.dequeueReusableCell(withIdentifier: "TodoCell") as! TodoCell

        cell.setTodo(todo: todo)

        return cell
    }
}

TodoCell.swift

import UIKit

class TodoCell: UITableViewCell {
    @IBOutlet weak var todoText: UILabel!

    func setTodo(todo: Todo) {
        todoText.text = todo.text
    }
}

Todo.swift

import Foundation

struct Todo {
    var text: String
    var done: Bool

    init(text: String, done: Bool = false) {
        self.text = text
        self.done = done
    }
}

Upvotes: 1

Views: 2364

Answers (4)

Yashvir Walia
Yashvir Walia

Reputation: 1

you can use this

func addTodo() {
   let todo1 = Todo(text: "My first todo")
   let todo2 = Todo(text: "My second todo")
   todos = [todo1, todo2]
   DispatchQueue.main.async {
      self.todosTable.reloadData()
   }
}

This might help you

Upvotes: 0

Amit
Amit

Reputation: 4896

You are adding the data to array after creating the tableView.

Change this line :

var todos: [Todo] = []

to

var todos: [Todo]! {
    didSet {
        self.todosTable.reloadData()
    }
}

and in numberOfRowsInSection :

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    guard (todos != nil) else {
        return 0
    }
    return todos.count
}

Upvotes: 0

ZbadhabitZ
ZbadhabitZ

Reputation: 2913

I succeeded in using your code to successfully generate your Todo rows (I did not reloadData() after calling addTodo());

enter image description here

Having proven that your code does work, it leads me to believe that you have an issue somewhere in your Storyboard setup, more-so than you do in your code itself. A few suggestions:

Verify your custom cell is subclassed as a TodoCell. You can do this by clicking on your TodoCell in Interface Builder, and in the Identity Inspector tab, verify you have this set to TodoCell:

enter image description here

This is likely not the issue as your app would more than likely crash if your cells were not subclassed properly.

Verify you have set the cell identifier in Interface Builder. Again, click on the TodoCell in Interface Builder, go to the Attributes Inspector tab, and verify identifier is set to TodoCell:

enter image description here

Also, do make sure that you've actually connected your tableView and todoText UILabel to your code. I see you have @IBOutlets to these items, but if you were copying and pasting from a tutorial, it's possible you typed in the items and never actually connected them. The gray circle next to your IBOutlet for both the tableView and UILabel should be filled in, like so:

enter image description here

If it's empty, you may not have a connection, which could explain the issue. Again, I copied and pasted your code verbatim and set things per the above suggestions; I do not believe that reloadData() or setting the number of sections will help the issue (as your code did not have them and it's working on my end).

Upvotes: 6

Kuldeep Tanwar
Kuldeep Tanwar

Reputation: 3526

You need to reload your tableview after updating the datasource :-

func addTodo() {
    let todo1 = Todo(text: "My first todo")
    let todo2 = Todo(text: "My second todo")
    todos = [todo1, todo2]
    todosTable.reloadData()
}

Edit I also noticed by looking at the JWC comment you didn't have the numberOfSection method implemented so you must also add the number of section delegate method.

Upvotes: 0

Related Questions