Macness
Macness

Reputation: 1226

Show a UIView when a variable meets a condition

I have a model object called PlayerStore which is an array of Player objects. These get added to the MainVC view controller's UITableView. Here a user can add Player objects that are displayed in UITableView.

I have a UILabel that is an @IBOutlet called pressPlusLbl that I want to only display when there are no players left in the PlayerStore.

I can handle that easily when the view loads in ViewDidLoad with something like:

    override func viewDidLoad() {
        super.viewDidLoad()

        players = store.getAllPlayers()
        emptyTableShowsLabel()

    }

    func emptyTableShowsLabel(){

        if !store.hasPlayers(){
            pressPlusLbl.isHidden = false
            // TODO: maybe animate this view?
            // TODO: hide the table
        } else {
            pressPlusLbl.isHidden = true
            // TODO: bring back the table
        }
    }

But I always want my view controller to listen to the model objects (PlayerStore) to know when it's empty: !store.hasPlayers() so that I can display the pressPlusLbl again.

EDIT 1:

Don't know if it's relevant, but here's one of the places the user can delete from the TableView:

func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
    if (editingStyle == .delete){

        store.deletePlayer(row: indexPath.row)
        players = store.getAllPlayers()
        tableView.deleteRows(at: [indexPath], with: UITableViewRowAnimation.bottom)

    }
}

EDIT 2: Looking to implement a delegate pattern from the PlayerStore. Here's what I have that builds but doesn't quite work.

in MainVC.Swift (View Controller) using my existing protocols:

protocol PlayerIncrementor {
    func increment(playerPosition: Int)
    func decrement(playerPosition: Int)
    func isStoreEmpty()
}

class MainVC: UIViewController, UITableViewDataSource, UITableViewDelegate, PlayerIncrementor {

...

    func isStoreEmpty() {

        store.delegate = self

        if store.hasPlayers() {
            pressPlusLbl.isHidden = true
        } else {
            pressPlusLbl.isHidden = false
        }

    }

}

In the PlayerStore.swift (Model)

class PlayerStore {

...

    var delegate: PlayerIncrementor!

    private var _playerArray = [Player]()

    func hasPlayers() -> Bool {
        return !_playerArray.isEmpty
    }


...

}

Upvotes: 0

Views: 157

Answers (3)

koropok
koropok

Reputation: 1413

You can use the Delegate pattern.

protocol MainViewControllerDelegate {
    func playersDidChange()
}

class MainViewController: UIViewController, MainViewControllerDelegate {

    func playersDidChange() {
        // Check store to determine if label is to be shown
    }
}

Then in your player store simply create a reference to the delegate and call delegate.playersDidChange function.

When you add/remove a player from your player store, you can call the delegate. For example,

class PlayerStore {

    func addPlayer(player: Player) {
        // Add player to your array
        delegate.playersDidChange()
    }

    func removePlayer(player: Player) {
        // Remove player from your array
        delegate.playersDidChange()
    }
}

So in your UITableViewDelegate function,

func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) 

By calling store.removePlayer function, your label isHidden will be handled by the MainViewControllerDelegate.

Also, you just have to set store.delegate = self once, probably right after you initialised the store.

Upvotes: 1

KSR
KSR

Reputation: 1709

Call checkTableData() after deleting the row:

func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
    if (editingStyle == .delete){

        store.deletePlayer(row: indexPath.row)
        players = store.getAllPlayers()
        tableView.deleteRows(at: [indexPath], with: UITableViewRowAnimation.bottom)
checkTableData()

    }
}

 func checkTableData() {

              if !store.hasPlayers(){
                        pressPlusLbl.isHidden = false
                        // TODO: maybe animate this view?
                        // TODO: hide the table
                    } else {
                        pressPlusLbl.isHidden = true
                        // TODO: bring back the table
                    }


            }

Don't forget to reload the tableView.

Upvotes: 0

Sachin Vas
Sachin Vas

Reputation: 1767

The best way to check this is where you basically editing the datasource. So, in your case numberOfRowsForSection, commitEditingStyle. If you try to insert also, you may need to remove the label if the datasource count goes higher.

Upvotes: 0

Related Questions