FREE TRIAL: Accelerate your app development career with Hacking with Swift+! >>

SOLVED: viewDidAppear() & NSTableView loading

Forums > macOS

My app uses three table views on the main screen. I am calling CoreData methods to retrieve that data at start up. I have the dataHelper data object property declared at the top of the view controller as var dataHelper: DataHelper which sets the proiperty to the DataHelper class. The loading of that data can take up to five seconds to fully load, at this point. I was thinking I could use the the viewDidAppear method in the view controller to instantiate my data object after the screen appears and the tables would then be populated on screen rather than the beachball being displayed for those five seconds and the view being fully populated when it appears. However, I moved the instantiation of the data object (dataHelper = DataHelper()) from viewDidLoad to the viewDidAppear method and the app still isn't displaying the screen until after the tables are populated. It introduced some other problems with my tableViews.

First, Is there something special to using this method? I have looked at tutorials on the web about view lifecycles and thought I understood how they work. I thought viewDidAppear meant the main app display was being actively displayed on the screen, but based on the five second blocking of the main thread that is not happening. I have also been using breakpoints and it appears the tableViews are running automatically before viewDidLoad() and viewDidAppear(). How do I not have the tableViews automatically load?

Here's the relevant code:

IBOutlet var mainTableView: NSTableView!
IBOutlet var secondTableView: NSTableView!

var dataHelper = DataHelper

override func viewDidAppear() {
        super.viewDidAppear()
        dataHelper = DataHelper()
        dataHelper.loadData()
        mainTableView.reloadData()
        secondTableView.reloadData()

I wasn't expecting the tableView methods to be called until after the loadData method was called on my dataHelper object. It makes sense I guess, but how do I make the tables just appear as empty tables until the reloadData() methods are called? The third table is not a problem and it's okay to be populated when the view appears as the data is created at startup.

I will eventually look into seting up the data object instatiation as a secondary thread, but figured viewDidAppear would work for now just for my development purposes.

   

I'm sure you figured this out, given that it's been four months, but anyways...

In your NSTableViewDataSource methods you need to add a condition to return 0 number of rows if the data is not ready yet. i.e., something like this:

func numberOfRows(in tableView: NSTableView) -> Int {
    if dataHelper.isReady {
      return dataHelper.items.count
    }

    return 0
  }

Then when your dataSource is ready, call tableView.reloadData()

   

Thank you for your response. No I did not get this figured out. I tried your suggestion, but I do not have an .isReady member. Do I need to build that into the Datahelper class? If so, what would that look like?

Presently I am using DispatchQueue to load the table in a separate thread as the data collection for loading the second TableView takes about 25 seconds or so and I did not want the interface blocked until that data is loaded. The unfortunate thing is when the first TableView is automatically loaded it selects the first item which then triggers the loading of the second TableView.

   

I thiink the easiest thing would be to not have any rows selected on the main table once it loads, which would then not trigger the loading (and delay) of the second table. I've tried setting mainTableView.selectedRow = -1 manually, but that creates an error in Xcode telling me it is a getting method only. So, I just keep plinking away and reading tutorials/documentation until I finally figure it out.

   

And just like that, I leave the above comment and then I find a posting at SO and in that post it suggested selecting "Empty" checkbox in the NSTableView Selection Attributes to not have a row initially selected. Now the second table does not automatically load at startup until a row is clicked in the main table.

   

Hacking with Swift is sponsored by Sentry

SPONSORED With Sentry’s error and performance monitoring for iOS you see mobile vitals that actually matter, can solve any latency issues quickly, and learn how each release is performing over time.

Get started

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.