BytesGuy
BytesGuy

Reputation: 4127

Changing nstabview item twice in one method

I have a NSTabView with several tab view items. When a user hits a certain button, the tabview changes to one of these items to display things returned from a website api. I tried to create an intermediate tab view item to tell the user that it is fetching the data and then once fetched it will display it.

[tabView selectTabViewItemAtIndex:0]; // This is the intermediate tab
/* 
   Fetching 
   data from
   the api
   here
*/
[tabView selectTabViewItemAtIndex:1]; // Displaying the data tab

But the first tab never gets shown, only the last one. I wondered if it was just getting the data very quickly and didn't have time to show it, but I set a breakpoint halfway through but it still hadn't been changed. It only seems to be getting changed at the end, weird.

Any ideas?

Update:

Thanks for the answer, fixed it as follows

[tabView selectTabViewItemAtIndex:0]; // This is the intermediate tab

dispatch_queue_t queue = dispatch_queue_create("com.mycompany.queue", 0);
dispatch_async(queue, ^{
    /* 
       Fetching 
       data from
       the api
       here
    */
    [tabView selectTabViewItemAtIndex:1]; // Displaying the data tab
});

Upvotes: 1

Views: 947

Answers (1)

Carter
Carter

Reputation: 4758

Does the API that fetches data operate synchronously? I'm willing to bet that it does.

The user interface is only going to update at the end of the run loop running on the main thread. If the API that handles the fetching runs in the same thread then things are going to end up working like this:

  1. Begin Run Loop
  2. You Select Tab Index 0
  3. You fetch the data.
  4. You Select Tab Index 1
  5. The UI updates, displaying tab index 1.

You probably need to run your data fetch routines in a background thread. Then when it returns data, tell the NSTabView to select tab index 1. Since the data fetch occurs in the background, the run loop will have a chance to update the UI more than once which should result in tab index 0 becoming visible (for a short while anyway).

You can run the data fetch in the background using a couple of different methods. The obvious ones are to use Grand Central Dispatch or you could also use the "performSelectorInBackground:" series of methods that are part of the NSObject protocol.

Also you should ALWAYS be very careful about what operations you perform on the main thread. Fetching data from a website could take a while. If you run that operation synchronously on the main thread then the user interface will be completely non responsive while you wait for that data fetch to complete. Apple talks about this in their documentation on multithreading.. Definitely worth a read. That and Grand Central Dispatch - it makes multithreading much much easier.

Upvotes: 2

Related Questions