iOS应用程序无法以正确的顺序异步加载Parse.com中的所有数据

时间:2015-04-16 03:53:12

标签: ios objective-c parse-platform

我是iOS开发的新手,我遇到了问题。我正在使用来自https://github.com/cwRichardKim/TinderSimpleSwipeCards

的代码为应用程序实现Tinder(如滑动功能)

这是我给你带来麻烦的代码。

imageCard = [[NSMutableArray alloc]init];
    PFQuery *query = [PFQuery queryWithClassName:@"Post"];
    [query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
        if (objects != nil) {
            NSMutableArray *imageDataArray = [[NSMutableArray alloc] init];
            for (PFObject *object in objects) {
                // add all image objects into imagesArray
                [imageDataArray addObject:object[@"content"]];
            }
            // loop through imageDataArray and get each image
            for (int i = 0; i < [imageDataArray count]; i++) {
                PFFile *imageFile = imageDataArray[i];
                [imageFile getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
                    if (!error) {
                        NSLog(@"loop: %d",i);
                        [imageCard addObject:[UIImage imageWithData:data]];
                        // ***** only loadCards after all images have been retrieved
                        if (i == [imageDataArray count] - 1) {
                            loadedCards = [[NSMutableArray alloc] init];
                            allCards = [[NSMutableArray alloc] init];
                            cardsLoadedIndex = 0;
                            NSLog(@"Cards loaded");
                            [self loadCards];
                        }
                    }
                }];
            }
        }
    }];

所以我正在查询Post表中所有图像的Parse。然后我将所有图像数据放在imagesArray中。然后我循环使用imagesArray并从后台线程中的图像数据中获取实际图像,并将实际图像放入另一个数组(imageCard)。将所有图像添加到imageCard后,我想加载卡片([self loadCards])。

假设imageDataArray有6个对象。现在的问题是getDataInBackgroundWithBlock异步运行6次。我只想在加载最后一个对象时加载[self loadCards],但最后一个对象可以在其他对象之前加载。这是一个视觉问题的控制台输出。

http://imgur.com/PwqT5Qm

正如你所看到的,数据没有按升序加载,它是随机加载的,并且“加载卡片”之后的任何内容都没有加载,这就是我需要帮助的问题。

谢谢!

1 个答案:

答案 0 :(得分:0)

您的问题正如您所指出的那样,异步任务将以未定义的顺序完成。 Grand Central Dispatch(GCD)使用调度组为waiting for a number of asynchronous tasks to complete提供了解决方案。

要使用它,您需要将异步Parse方法getDataInBackgroundWithBlock替换为同步版本getData,并自行将任务分派到异步队列中 -

imageCard = [[NSMutableArray alloc]init];
PFQuery *query = [PFQuery queryWithClassName:@"Post"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
    if (objects != nil) {
        NSMutableArray *imageDataArray = [object valueForKey:@"content];

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

            // loop through imageDataArray and get each image

        for (PFFile *imageFile in imageDataArray) {
            dispatch_group_async(group, queue, ^{
                NSData *data=[imageFile getData] 
                if (data!=nil) {
                    NSLog(@"loop: %d",i);
                    [imageCard addObject:[UIImage imageWithData:data]];
                }
            });
         }
// 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);

         loadedCards = [[NSMutableArray alloc] init];
         allCards = [[NSMutableArray alloc] init];
         cardsLoadedIndex = 0;
         NSLog(@"Cards loaded");
         [self loadCards];
    }
}];