简体   繁体   中英

Parse.com query and application design issue: A long-running operation is being executed on the main thread

In my iOS app I need to retrieve some values by using PFObject queries. And when these are all loaded, the app should continue doing some more stuff.

func processTransaction(){

   .. some code to prepare my 2 queries

   var balance1 = balance1Query.getFirstObject() as PFObject;
   var balance2 = balance2Query.getFirstObject() as PFObject;

   .. after these are loaded i have to update them, and 'release' the screen to the user. 
}

Now, when using this .getFirstObject() method, I get a warning in my Xcode debug window saying:

A long-running operation is being executed on the main thread.

Of course I did some research, and every answer I read talks about using getObjectInBackgroundWithId , which then moves the execution of these queries to the background (I guess doing so it puts them on a new thread.)

But my question is, how should I structure my code / design, to make sure that both objects are loaded, before the code continues to work with these objects?

I tried some things, and create some code like below, but to me it feels like this isn't the right approach. Can't think of what a mess this will become when I have to load and make sure that 4 or 5 objects are loaded.

balanceQuery1.getFirstObjectInBackgroundWithBlock{
    (balance1: PFObject!, error1: NSError!) -> Void in
    if error1 == nil {
        balanceQuery2.getFirstObjectInBackgroundWithBlock{
            (balance2: PFObject!, error2: NSError!) -> Void in
            if error2 == nil {
                ... processing here..
            }
    }
}

My suggestion that your approach was correct was based on the requirement to execute two queries - In this case you can dispatch the first query into the background and then execute the subsequent query in the completion block.

If you are looking for a more general asynchronous dispatch model then I would suggest using dispatch groups to synchronise the activities. To use this technique effectively it is best to have your queries in an array or similar data structure. (Apologies, I haven't converted this to Swift, but it is essentially the same)

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();

// Add a task to the group

for (int i=0;i<self.queries.count;i++) {


    dispatch_group_async(group, queue, ^{
       self.queries[i].getFirstObject ...
    });
}

// When you cannot make any more forward progress,
// wait on the group to block the current thread.
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

// Release the group when it is no longer needed.
dispatch_release(group);

If you want to avoid nesting, there is a second approach that can be useful, especially if you have a LOT of queries to run. Three steps:

  1. Set an int completedQueries variable to 0 that will be incremented when a query finishes
  2. Set an int totalQueries variable that represents the total number of queries to finish
  3. For each query's completion block, increment completedQueries and run a function to check if the number of completions is equal to the total:

     balanceQuery1.getFirstObjectInBackgroundWithBlock{ (balance1: PFObject!, error1: NSError!) -> Void in if error1 == nil { completedQueries++ checkQueriesCompleted() } } //balanceQuery2, 3 and so on below... 

Finally, have a checkCompletedQueries function that waits until your total and completed are equal:

func checkQueriesCompleted() {
    if (completedQueries == totalQueries) {
        //... processing here ....
    }
}

This structure is especially powerful if you have 3+ functions, or you have an arbitrary number of calls. I use it a lot when I want to get around the 1000 item return limit on Parse (get a total number of objects, make as many calls as I need with a .skip parameter, wait for all returns before processing) - you get the idea.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM