Firebase直接从Storage下载图像

时间:2016-06-30 23:06:57

标签: objective-c uitableview firebase storage

开始使用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中显示图像。

但是由于后台下载和reloadData之间的延迟,所以不会显示任何图像。

任何想法或解决方案?

1 个答案:

答案 0 :(得分:1)

在加载图片时阻止主线程并不是一个好主意,否则应用程序将对用户完全没有响应。相反,您只是希望在完成所有下载后收到通知,然后重新加载表视图。这可以通过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时,我们的块被调用,我们知道所有操作都已完成,重新加载表视图是安全的。此外,此方法不会阻止主线程,这意味着用户仍然可以在下载过程中与UI进行交互。