开始使用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之间的延迟,所以不会显示任何图像。
任何想法或解决方案?
答案 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进行交互。