Firebase 直接从存储中下载图像

Firebase download image from Storage directly

开始使用 Firebase,到目前为止我喜欢它。但现在我在顶 - 试图从存储中下载图像。但是我不想在后台下载图片,我想直接下载它们-希望我清楚。

到目前为止我测试过:

for (NSInteger iLoop=0; iLoop<aFriendsKey.count; iLoop++) {
            NSDictionary *dicFriend = [dicFriends objectForKey:[aFriendsKey objectAtIndex:iLoop]];
            FIRStorage *storage = [FIRStorage storage];
            FIRStorageReference *storageRef = [storage referenceForURL:[dicFriend objectForKey:@"avatarURL"]];
                            // Download in memory with a maximum allowed size of 1MB (1 * 1024 * 1024 bytes)
            [storageRef dataWithMaxSize:5 * 1024 * 1024 completion:^(NSData *data, NSError *error){
                if (error != nil) {
                    // Uh-oh, an error occurred!
                } else {
                    [aFriendsAvatar addObject:data];
                }
            }];
        }
        [_tvFriends reloadData];

它工作正常,但图像没有及时下载,这意味着当我重新加载 UITableView 时它们不可用。正如您从之前的代码中看到的,我正在尝试将所有图像加载到 NSMutableArray 中,并使用此 NSMutableArray 在 UITableView 中显示图像。

但由于后台下载和重新加载数据之间的延迟,从未显示任何图像。

有什么想法或解决方案吗?

在加载图像时阻塞主线程不是一个好主意,否则应用程序将变得对用户完全没有响应。相反,您只是想在所有下载完成后收到通知,然后重新加载 table 视图。这可以通过来自 Grand Central Dispatch (GCD) 的 dispatch_group_t 来完成。

dispatch_group_t group = dispatch_group_create();

for (NSInteger iLoop=0; iLoop<aFriendsKey.count; iLoop++) {
    NSDictionary *dicFriend = [dicFriends objectForKey:[aFriendsKey objectAtIndex:iLoop]];
    FIRStorage *storage = [FIRStorage storage];
    FIRStorageReference *storageRef = [storage referenceForURL:[dicFriend objectForKey:@"avatarURL"]];
    // Download in memory with a maximum allowed size of 1MB (1 * 1024 * 1024 bytes)
    dispatch_group_enter(group);
    [storageRef dataWithMaxSize:5 * 1024 * 1024 completion:^(NSData *data, NSError *error){
        if (error != nil) {
            // Uh-oh, an error occurred!
        } else {
            [aFriendsAvatar addObject:data]
        }
        dispatch_group_leave(group);
    }];
}

dispatch_group_notify(group, dispatch_get_main_queue(), ^{

    [_tvFriends reloadData];
});

您可以将调度组视为未完成操作的简单计数器。在我们开始每次下载之前,我们调用组上的 dispatch_group_enter 来增加它的计数。每次下载完成后,我们调用 dispatch_group_leave 来减少计数。我们用 dispatch_group_notify 注册一个侦听器块,这样当计数达到 0 时,我们的块被调用并且我们知道所有操作都已完成,并且可以安全地重新加载 table 视图。此外,这种方法不会阻塞主线程,这意味着用户仍然可以在下载过程中与 UI 交互。