ios 上的 Firebase 检索数据缓慢

Firebase on ios is slow in retrieving data

我了解到,保持 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];
    }
}

但是,self.distanceMutableArray 之前的 for 循环 运行 可以填充。这会抛出一切,因为 for 循环依赖于 self.distanceMutableArray 被填充。

有没有一种方法可以检索数据,使代码 运行 流畅并按编写的顺序进行?

这里的问题是 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 中的存储方式,这样您就可以一起检索数据,而不必进行多次观察调用。