我已经读过,保持Firebase的数据更加平坦以及仅嵌套您打算调用的数据非常重要。我已经完成了这些工作,但Firebase在检索数据方面仍然太慢。这是一个例子:
我的数据如下:
--English
----Ari : 4
----Philip : 2
----John : 6
我的代码看起来像这样:
[super viewDidLoad];
[[DataSource sharedInstance].selectedLanguageMutableArray removeAllObjects];
//Retrieving Data From Firebase
NSString* selectedLanguagePath = [NSString stringWithFormat:@"languages/%@", [DataSource sharedInstance].languageSelected];
Firebase *languagesRef = [[DataSource sharedInstance].ref childByAppendingPath:selectedLanguagePath];
[[languagesRef queryOrderedByValue] observeEventType:FEventTypeChildAdded withBlock:^(FDataSnapshot *snapshot) {
[self.distanceMutableArray addObject:snapshot.key];
NSLog(@"%@", snapshot.key);
NSLog(@"%@", snapshot.value);
NSLog(@"%@", self.distanceMutableArray);
}];
//Selected Languages Mutable Array
[[DataSource sharedInstance].selectedLanguageMutableArray removeAllObjects];
for (NSInteger i = 0; i < self.distanceMutableArray.count; i++) {
UserCustomizationData *item = [[UserCustomizationData alloc] init];
NSString* selectedUser = self.distanceMutableArray[i];
Firebase* selectedUserRef = [[DataSource sharedInstance].usersRef childByAppendingPath:selectedUser];
if (selectedUser.length > 0) {
Firebase* profilePicRef = [selectedUserRef childByAppendingPath:@"profilePicture"];
[profilePicRef observeEventType:FEventTypeChildAdded withBlock:^(FDataSnapshot *snapshot) {
NSString* profPicString = snapshot.value;
NSData *dataFromBase64=[NSData base64DataFromString:profPicString];
UIImage *profPicImage = [[UIImage alloc]initWithData:dataFromBase64];
item.profilePicture = profPicImage;
}];
[[DataSource sharedInstance].selectedLanguageMutableArray addObject:item];
}
}
但是,for循环在self.distanceMutableArray可以填充之前运行。这会抛出一切,因为for循环依赖于填充的self.distanceMutableArray。
有没有办法检索数据,以便代码能够以编写的顺序流畅地运行?
答案 0 :(得分:0)
这里的问题是Firebase通过异步调用工作;您的代码将无法一致地工作,因为可能在块完成之前调用Firebase块下面的代码。
您需要异步开始编码,并且只有在确定已填充(在块内)后才对快照数据执行操作
[[languagesRef queryOrderedByValue] observeEventType:FEventTypeChildAdded withBlock:^(FDataSnapshot *snapshot) {
//at this point, firebase has loaded the snapshot
// so its available to work with
[self.distanceMutableArray addObject:snapshot.key];
for (NSInteger i = 0; i < self.distanceMutableArray.count; i++) {
//do some stuff with the items in snapshot
}
}];
//don't work with anything that was from the snapshot as it may have not been filled yet
然而,由于代码使用了childAdded,因此会出现问题,因此会迭代firebase节点中的每个项目,因此代码将无法正常工作,因为它无法正确加载数组(是的,我们可以通过在每个循环期间填充数组。)
此处的另一个挑战是您需要根据第一个快照的结果从Firebase检索数据。同样,存在同样的情况;只有在您确定已检索到数据后才会对检索到的数据执行操作。
一种解决方案是一次加载整个数据集并对其进行迭代(按值而不是添加)。如果您的数据集较小则有效。但是,对于可能太多的大数据集。
[[languagesRef queryOrderedByValue] observeEventType:FEventTypeValue withBlock:^(FDataSnapshot *snapshot) {
//at this point, firebase has loaded the snapshot
// so its available to work with and loaded with
//everything in the node
for ( FDataSnapshot *child in snapshot.children) {
NSDictionary *dict = child.value;
NSString *uid = child.key;
[self.distanceMutableArray addObject:uid];
}
// now the array is loaded do something with it
}];
另一种选择是更改数据在firebase中的存储方式,以便您可以一起检索数据,这样就不必进行多次观察调用。