2

In my class I have multiple Resource Siesta objects that I want all loaded with data before I populate the table view and enable user input.

Here's the code:

var trainees: Resource? {
    didSet {
        oldValue?.removeObservers(ownedBy: self)

        trainees?.addObserver(self).addObserver(statusOverlay, owner: self).loadIfNeeded()
    }
}

var points: Resource? {
    didSet {
        oldValue?.removeObservers(ownedBy: self)

        points?.addObserver(self).addObserver(statusOverlay, owner: self).loadIfNeeded()
    }
}

var exercises: Resource? {
    didSet {
        oldValue?.removeObservers(ownedBy: self)

        exercises?.addObserver(self).addObserver(statusOverlay, owner: self).loadIfNeeded()
    }
}

func resourceChanged(resource: Siesta.Resource, event: Siesta.ResourceEvent) {
    tableView.reloadData()
}

override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)

    self.trainees = DataManager.sharedInstance.api.trainees
    self.points = DataManager.sharedInstance.api.points
    self.exercises = DataManager.sharedInstance.api.exercises
}

So the question is what is the best way to check that everything has been loaded before calling reloadData in the resourceChanged func. Thanks.

Rhuantavan
  • 445
  • 3
  • 17

1 Answers1

0

Option 1

If you’re using Siesta’s built-in ResourceStatusOverlay, and if the same status overlay is observing all three resources, then the overlay won’t go away until all three are loaded. One option is to just let the overlay cover everything while they’re loading, even as the tableview gets partly populated underneath.

Option 2

If your logic breaks unless all the data is present, you can check that all three resources have data before touching the table view:

func resourceChanged(resource: Siesta.Resource, event: Siesta.ResourceEvent) {
    if trainees.latestData != nil && points.latestData != nil && exercises.latestData != nil {
        tableView.reloadData()
    }
}

Note that doing it this way would leave the table view populated even after a resource.wipe() call. If you are logging the user out with service.wipeResources(), then this could lead to user data remaining on the screen even after logout. The solution would be to populate some data structure with either all the data or none, but to call reloadData() in either case:

func resourceChanged(resource: Siesta.Resource, event: Siesta.ResourceEvent) {
    if trainees.latestData != nil && points.latestData != nil && exercises.latestData != nil {
        dataToDisplayInTable = .......;
    } else {
        dataToDisplayInTable = [];
    }
    tableView.reloadData()
}

Option 3

Ensure that your logic handles resources with or without data, and populate the table view incrementally as the resources get populated:

func resourceChanged(resource: Siesta.Resource, event: Siesta.ResourceEvent) {
    // This is made-up logic; insert your real logic here.
    // Note that this example works because jsonArray returns []
    // for a resource with no data.
    dataToDisplayInTable = trainees.jsonArray
                         + points.jsonArray
                         + exercises.jsonArray

    tableView.reloadData()
}

Because of the lazy cell creation in table views, this approach is rarely a performance concern.

Paul Cantrell
  • 9,175
  • 2
  • 40
  • 48
  • Thanks for the wonderful answer! I guess I have nothing to worry here using the 1st option. – Rhuantavan Oct 20 '15 at 15:03
  • 1
    You’re welcome. ResourceStatusOverlay is something of a first draft, not tested in every possible circumstance (but only where it’s been used), so please file issues on Github if it does not work satisfactorily. – Paul Cantrell Oct 20 '15 at 15:05