NOTE:所有代码均采用 Objective-C 编写,但此特定代码的翻译应该很简单。如果有人想编辑我的帖子以包含 Swift 代码,请随意,但请在帖子中保留 Objective-C。
我做什么(为了UICollectionView
or UITableView
) 是创建一个属性,通常称为isLoading
像这样:
@property (assign, nonatomic) BOOL isLoading;
我通常这样初始化它:
- (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];
}
现在,真正的秘密当然是你必须在你的程序中实现逻辑。UICollectionViewDataSource
有条件地显示数据的方法self.isLoading
, 像这样:
- (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
}
}
一般来说,这就是我需要让屏幕延迟加载的全部内容UICollectionView
直到解析查询正确返回。
当我有多个查询同时运行时,所有这些查询都应该在我认为数据加载完成之前返回,然后我创建一个BOOL
属性为每个,设置适当的标志,并且我通过一个漏斗所有查询返回checkIfDone
方法。像这样的东西:
@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:这假设任何后续调用loadData
将在后台发生,并且任何后续调用[collectionView reloadData]
仅在查询调用结束时发生。如果有其他事情可能会打电话reloadData
同时,您将需要更高级的逻辑来确保正确加载正确的数据。
边注:执行此类操作时,不要忘记向用户显示工作正在进行中的指示。我喜欢使用开源MBProgressHUD
。可用在 GitHub 上 https://github.com/jdg/MBProgressHUD。我发现它对于完全按照你所说的去做是非常有价值的。