hell2809
hell2809

Reputation: 35

Reload UITableView that is inside UIViewController

I'm learning swift and today I got a problem. I'm creating an app that displays movie theaters and their schedules. Something like this:

enter image description here

The idea is there are 3 buttons which will show a theater's schedule for today, the next day and the day after that ( I don't know the right word, sorry :( ) if clicked. For example, the first button shows today's schedule:

enter image description here

First time the view is load, it always shows today's schedule. But the other buttons don't work and I don't know why.

I got tableView's delegate and datasource in UIViewController's viewDidLoad method.

enter image description here

override func viewDidLoad() {
    super.viewDidLoad()

    // Delegate/datasource for tableView that shows theater's schedule
    showtimeTable.delegate = self
    showtimeTable.dataSource = self
    showtimeTable.tableFooterView = UIView()

Here is the action func. Because 3 buttons has the same purpose so I connected them all to 1 func, I tested and they worked fine with the "get button text" method.

enter image description here

@IBAction func isClickedDate(_ sender: UIButton) {
    selectedDay = Int(sender.titleLabel!.text!)!
}

After the day is selected, the app will go throw all the rooms of selected theater and all the shows in each room and pick every show that has the same day as selectedDay, store them in a list and return to a global variable showOnDate: [Show]

extension ShowtimeViewController: UITableViewDelegate, UITableViewDataSource {

// MARK: Showtime tableView lifecycle and settings

// Set number of section based on number of show performed on selected day
func numberOfSections(in tableView: UITableView) -> Int {
    return showOnDate.count
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 1
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "showtimeCell", for: indexPath) as! ShowtimeTableViewCell
    return cell
}

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    let cell = cell as! ShowtimeTableViewCell
    let dateTimeComponents = Calendar.current.dateComponents(dateComponents, from: showOnDate[indexPath.section].sDate)

    // Set cell image and labels based on shows of selected theater
    cell.showImage.image = showOnDate[indexPath.section].sFilm.fPoster
    cell.showName.text = "\(showOnDate[indexPath.section].sFilm.fName) (\(showOnDate[indexPath.section].sFilm.fYear))"
    cell.showTime.text = "\(dateTimeComponents.hour!):\(dateTimeComponents.minute!)"
}

// Get shows will be performed on selected date
func getShowList(date: Int) -> [Show] {
    var listShow = [Show]()
    for room in selectedTheater!.tRooms {
        for show in room.rShow {
            let dateTimeComponents = Calendar.current.dateComponents(dateComponents, from: show.sDate)
            if date == dateTimeComponents.day! {
                listShow += [show]
            }
        }
    }
    return listShow
}

}

I tried to include showtimeTable.reloadData() in the action func but nothing happened. Tried DispatchQueue.main.async, beginUpdates() and endUpdates(), nothing worked ( I tried everything I know so maybe it didn't even have any impact ). Now I'm crying and I need help. Thanks a lot! ( I don't have enough reputation to embed image, sorry :( )

Upvotes: 1

Views: 413

Answers (2)

Lorenzo B
Lorenzo B

Reputation: 33428

The action linked to the button is doing nothing, except changing the value of selectedDay variable.

So, my question is: in which manner are you retrieving the elements you are going to display in the table view? i.e. Can you show the implementation for your data source methods?

Here you can have different ways to achieve it. A simple one is to assign to showOnDate variable, a new list based on that selection and, after that, trigger reloadData method. You don't need to perform any dispatch to main if you are already running on the main thread.

Sample:

@IBAction func isClickedDate(_ sender: UIButton) {
    selectedDay = Int(sender.titleLabel!.text!)!
    showOnDate = getShowList(selectedDay)
    tableView.reloadData()
}

Note:

I would avoid to use this code

Int(sender.titleLabel!.text!)!

since is quite ugly. Maybe (just for learning new things) you can use the tag property for achieving this. The code will become more clean.

button.tag = 22
button2.tag = 23
// etc

and

@IBAction func isClickedDate(_ sender: UIButton) {
    showOnDate = getShowList(sender.tag)
    tableView.reloadData()
}

Upvotes: 0

vadian
vadian

Reputation: 285250

In the button action you need to update the showOneDate array with the shows related to selectedDay (like in viewDidLoad) and then reload the table view

@IBAction func isClickedDate(_ sender: UIButton) {
    selectedDay = Int(sender.titleLabel!.text!)!
    showOnDate = getShowList(date: selectedDay)
    tableView.reloadData()
}

The reason to post (more) code as text is that the people who are willing to help are not necessarily willing to retype all the code 😉


A suggestion:

Rather than getting the integer from the titleLabel I'd assign appropriate tags to the buttons, then you can simply write selectedDay = sender.tag

Upvotes: 1

Related Questions