iosobjective-cparse-platformgrand-central-dispatchserial-processing

GCD serial queue does not seem to be serially executed when using Parse


Thanks in advance for any help. I am trying to create an app that allows a user to answer questions and add their own for a group of people. I am downloading stock questions from parse, and for a variety of reasons, I need these question to be loaded into a main array in a specific order. I am trying to accomplish this with a serial GCD queue, but this is consistently switching between the expected result and the opposite result. It doesn't make sense to me, but I cannot shake the feeling that it may have something to do with async download requests used with the parse query, and none of the other answers here address.

Here is my code:

- (void)viewDidLoad{
[super viewDidLoad];


//Load the question with Central Dispatch to ensure load order
dispatch_queue_t my_queue = dispatch_queue_create("com.suresh.methodsqueue", NULL);
dispatch_async(my_queue, ^{
    //Load the inital questions
    if (self.objectQuestions == nil) {
        [self loadQuestionsWithClassName:@"FirstHundred"];
    }
});
dispatch_async(my_queue, ^{
    //Load the paid questions
    [self loadQuestionsWithClassName:@"PaidQuestions"];
});
}

This is the helper method I wrote:

-(void)loadQuestionsWithClassName:(NSString *)tempString {
//Query from Parse
PFQuery *query = [PFQuery queryWithClassName:tempString];
[query orderByAscending:@"createdAt"];
[query findObjectsInBackgroundWithBlock:^(NSArray *firstobjects, NSError *error) {
    if (!error) {
        // The find succeeded. Relay that information.
        NSLog(@"Successfully retrieved %lu items from user %@", (unsigned long)firstobjects.count, [[PFUser currentUser] objectId]);

        //Clear the objectQuestions temporary array and load the new Questions with the QuestionAndAnswers class
        self.objectQuestions = nil;
        self.objectQuestions = (NSMutableArray *)firstobjects;
        int n;
        int x = 0;
        int z = (int)[[MainQuestionList sharedInstance].mainQuestionList count];
        for (n=(int)[[MainQuestionList sharedInstance].mainQuestionList count]; n<[self.objectQuestions count]+z; ++n)
        {
            QuestionsAndAnswers *startQuestion = [[QuestionsAndAnswers alloc] init];
            startQuestion.questionNumber = &(n)+1;
            PFObject *object = [self.objectQuestions objectAtIndex:x];
            startQuestion.question = [object objectForKey:@"question"];
            startQuestion.answer = 0;
            startQuestion.starred = NO;
            startQuestion.answered = NO;
            startQuestion.category = [object objectForKey:@"Category"];
            ++x;


            [[MainQuestionList sharedInstance].mainQuestionList addObject:startQuestion];
        }

        //Find the first unanswered question
        while ([[MainQuestionList sharedInstance].mainQuestionList[self.mainQuestionNumber] answered] == YES) {
            ++self.mainQuestionNumber;
        };
    } else {
        // Log details of the failure
        NSLog(@"Error: %@ %@", error, [error userInfo]);
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Sorry!" message:@"We are sorry. Something seems to have gone wrong loading the app. Please check your internet connection and restart the app!" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
        [alertView show];
    }
}];

}

Again, any help is much appreciated!


Solution

  • What you're doing here is you're serializing asynchronous calls to the Parse library. So although each -[PFQuery findObjectsInBackgroundWithBlock:] are being queued synchronously, those functions themselves are asynchronous. You can try using the -[PFQuery findObjectsWithError:] method, a synchronous method, to ensure that your method calls return in the right order.