ios上的Firebase检索数据的速度很慢

时间:2015-12-10 21:10:34

标签: ios objective-c firebase data-retrieval

我已经读过,保持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。

有没有办法检索数据,以便代码能够以编写的顺序流畅地运行?

1 个答案:

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