In Swift, how to stop all the process until datas retrieved from parse.com in UICOLLECTIONVIEW

让人想犯罪 __ 提交于 2019-12-02 09:33:44

NOTE: All code is in Objective-C, but the translation for this particular code should be trivial. If someone wants to edit my post to include the Swift code, please feel free, but please leave the Objective-C in the post.

What I do (for UICollectionView or UITableView) is create a property, normally called isLoading like this:

@property (assign, nonatomic) BOOL isLoading;

I normally initialize it like this:

- (void)viewDidLoad {
    [super viewDidLoad];
    // This could also be done in viewWillAppear/viewDidAppear
    // based on your needs/desires
    self.isLoading = NO;
    [self loadData];
}

- (void)loadData {
    if (self.isLoading == YES) {
        // Just in case a "loadData" call is made while one is pending...
        return;
    }
    // Prevent this method from firing again until 
    // data loading is done; prevent UICollectionView
    // from attempting to display missing data
    self.isLoading = YES;

    // Do whatever you need to do...

    // Clean up and prepare for UICollectionView
    self.isLoading = NO;
    [self.collectionView reloadData];
}

Now, the real secret is, of course, that you have to implement logic in your UICollectionViewDataSource methods to display data conditionally based upon self.isLoading, like this:

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    if (self.isLoading == YES) {
        // You might want to return 0 or 1, 
        // depending on whether you have a "loading"
        // placeholder cell. Assume you do:
        return 1;        
    } else {
        // Return whatever is the correct number here

    }
}

Generally, that's all I need to get my screen to delay loading the UICollectionView until the Parse query has returned correctly.

When I have multiple queries that will run concurrently, all of which should return before I consider data loading to be complete, then I create a BOOL property for each of them, setting the flags as appropriate, and I funnel all query returns through a checkIfDone method. Something like this:

@property (assign, nonatomic) BOOL data1Loaded;
@property (assign, nonatomic) BOOL data2Loaded;
@property (assign, nonatomic) BOOL data3Loaded;
@property (assign, nonatomic) BOOL data4Loaded;

- (void)loadData {
    if (self.isLoading == YES) {
        return;
    }
    self.isLoading   = YES;
    self.data1Loaded = NO;
    self.data2Loaded = NO;
    self.data3Loaded = NO;
    self.data4Loaded = NO;

    // Call each of the separate data loading methods...
    [self loadData1];
    [self loadData2];
    [self loadData3];
    [self loadData4];

    // Notice that I don't do any reloadData calls here...

}

- (void)loadData1 {
    PFQuery *query = // Some query creation...
    [query findObjectsInBackgroundWithBlock:
        ^(NSArray *objects, NSError *error) {
            if (error != nil) { 
                // Handle "got error"

            } else {
                // Handle "got good data"

            }
            // Either way, #1 is done, so:
            self.data1Loaded = YES;
            // This pattern checks for completion and
            // runs the completion code only when all
            // 4 (in this case) items/queries have returned
            [self checkIfDone];
        }
     ];
}

- (void)checkIfDone {
    if (self.data1Loaded == YES && 
        self.data2Loaded == YES && 
        self.data3Loaded == YES && 
        self.data4Loaded == YES) 
    {
        // Clean up and prepare for UICollectionView
        self.isLoading = NO;
        [self.collectionView reloadData];
    }
}

Caveat: This assumes that any subsequent calls to loadData will occur in the background and that any subsequent calls to [collectionView reloadData] will only take place at the end of your query calls. If anything else might call reloadData in the meantime, you will need more advanced logic to ensure that the correct data is loaded correctly.


Side Note: When doing something like this, don't forget to show the user an indication that work is progressing. I like to use the open source MBProgressHUD. It's available here on GitHub. I have found it invaluable for doing exactly what you're talking about doing.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!