1

I have 4 UITableView's on my iPAD application. I load the data on them using a function loadData ,which is there in all the 4 TableViewController.m files, which makes calls to the database.

So, I would be doing something like this

[aView loadData];
[bView loadData];
[cView loadData];
[dView loadData];

Where aView, bView, cView and dView are the view controllers of the UITableView's.

However, the database calls happen synchronously and hence only after the data is retrieved from the [aView loadData] function, does the [bView loadData] function get called and so on.

This affects my performance.

I would like to know if there is a way I can asynchronously make calls to the database/ asynchronously make calls to functions which calls database.

It would be great if someone could help me out with this.

learner2010
  • 4,157
  • 5
  • 43
  • 68

1 Answers1

9

You can use GCD for this:

-(void)loadList
{
   // You ma do some UI stuff
   [self.activityIndicator startAnimating]; // for example if you have an UIActivityIndicator to show while loading

   // Then dispatch the fetching of the data from database on a separate/paralle queue asynchronously (non-blocking)
   dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

      // this is executed on the concurrent (parallel) queue, asynchronously
      ... do your database requests, fill the model with the data

      // then update your UI content.
      // *Important*: Updating the UI must *always* be done on the main thread/queue!
      dispatch_sync(dispatch_get_main_queue(), ^{
          [self.activityIndicator stopAnimating]; // for example
          [self.tableView reloadData];
      });
   });
}

Then when you will call the loadList method, the activityIndicator will start animate, and the fetching process of your data will be started on a separate queue asynchronously, but the loadList method will return immediately (not waiting for the block in dispatch_async to finish executing, that's what dispatch_async is for).

So all your call to your 4 loadList implementations in each of your viewcontrollers will execute immediately, (triggering the fetching of your data asynchronously but not waiting for the data to be retrieved). Once the database requests -- that was executing in a parallel queue -- have finished in one of your loadList method, the dispatch_sync(...) line at the end of the block is executed, asking the main queue (main thread) to execute some code to refresh the UI and display the newly-loaded data.

AliSoftware
  • 32,623
  • 6
  • 82
  • 77
  • I've edited my answer and added some details. Yes you should add this piece of code in each of your `loadData` functions that's better (or you could instead enclose the `loadData` calls with `dispatch_async(...)` in the caller code but that won't be very nice and readable, and it is the responsability of the ViewControllers to trigger the update of their associated view, so that's their work to call `[self.tableView reloadData]`). – AliSoftware Oct 03 '11 at 18:06
  • For your second question: the main queue in my code is retrieved using the `dispatch_get_main_queue()` function. Read the [Concurrency Programming Guide](http://developer.apple.com/library/ios/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html#//apple_ref/doc/uid/TP40008091-CH102-SW1) for more info about Grand Central Dispatch (GCD) & dispatch queues – AliSoftware Oct 03 '11 at 18:06
  • it worked perfectly. I would like to ask another major thing. in my loadData functions, I have calls to webservices. So what I do is that, if there is nothing in my database, I make a call to the webservice. when using this async functions, The call to the WS happens but after that nothing happens. What am I doing wrong? – learner2010 Oct 03 '11 at 18:46
  • How do you make your webservice calls? Using `NSURLConnection` and its asynchronous API? If so that's the good solution, but know then that when starting a request using `NSURLConnection`'s `connectionWithRequest:`, the request is scheduled on the NSRunLoop of the thread from which it is called, to be handled properly. I guess this is the reason of your download not happening (if it was working before)... So basically I guess you should either setup a runloop or more simply call your webservice on the main thread (which is not a problem if you use the asynchronous API of `NSURLConnection`) – AliSoftware Oct 03 '11 at 18:54
  • yes I am using NSURLConnection. so again when u say call your webservice on the main thread, that would mean after the closing bracket of dispatch_async.. am I right? – learner2010 Oct 03 '11 at 19:02
  • If you put anything after the closing bracket of dispatch_async it will be executed right away. Think of `dispatch_async(...,^{ some code });` as meaning: "start a background thread that will execute `somecode` in the background; and meanwhile, continue executing the code after the closing bracket of `dispatch_async(...)`". So instead, to call your webservice on the main thread, enclose the call with a `dispatch_sync(dispatch_get_main_queue(),^{...});` like I did for the part that updates the UI. – AliSoftware Oct 03 '11 at 22:36