Firebase on ios is slow in retrieving data

2020-05-06 08:43发布

I've read that it's important to keep data flatter for Firebase and to also only nest data that you intend to call. I've done those things, but Firebase is still too slow at retrieving data. Here's an example:

My data looks like this:

--English
----Ari : 4
----Philip : 2
----John : 6

And my code looks like this:

[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];
    }
}

However, the for loop runs before the self.distanceMutableArray can populate. This throws everything off because the for loop relies on the self.distanceMutableArray being populated.

Is there a way to retrieve data such that the code will run fluidly and in the order that it is written?

1条回答
萌系小妹纸
2楼-- · 2020-05-06 08:58

The issue here is that Firebase works via asynchronous calls; your code will not work consistently because the code below the Firebase block may be called before the block completes.

You will need to start coding asynchronously and only perform actions on snapshot data after you know for sure it has been populated (inside the block)

       [[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

However there's an issue as the code is using childAdded, so that will iterate over each item in the firebase node, so that code won't work either as it won't load the array correctly (yes we can fix that by populating the array during each loop).

The additional challenge here is that you need to retrieve data from Firebase based on the result of your first snapshot. Again, same situation exists; only perform actions on that retrieved data after you know for sure it has been retrieved.

One solution is to load in the entire dataset at one time and iterate over it (by value instead of added). If your data sets are smaller that works. However, for big datasets that can be too much.

[[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

}];

Another option is to change how your data is stored in firebase so you can retrieve data together so you dont have to make multiple observe calls.

查看更多
登录 后发表回答