Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/gwt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios UICollectionView-下载图像并有效地重新加载数据,如Instagram_Ios_Objective C_Cocoa Touch_Afnetworking_Uicollectionview - Fatal编程技术网

Ios UICollectionView-下载图像并有效地重新加载数据,如Instagram

Ios UICollectionView-下载图像并有效地重新加载数据,如Instagram,ios,objective-c,cocoa-touch,afnetworking,uicollectionview,Ios,Objective C,Cocoa Touch,Afnetworking,Uicollectionview,我注意到像Intagram这样的应用程序使用UICollectionViews来显示照片提要。 我还注意到,在实际照片完全下载之前,这些照片的单元格以某种方式被放置在屏幕上。然后,当下载完成时,该照片会很好地显示在正确的单元格中 我想复制这个功能,但我不知道该怎么做 我目前正在下载一个大型的JSON对象,我将其转换为一组NSDictionary。每个NSDictionary都包含关于每张照片的信息,在这些信息中,会显示一个URL。在这个URL上,我可以找到需要下载并显示在我的UICollecti

我注意到像Intagram这样的应用程序使用
UICollectionViews
来显示照片提要。 我还注意到,在实际照片完全下载之前,这些照片的单元格以某种方式被放置在屏幕上。然后,当下载完成时,该照片会很好地显示在正确的单元格中

我想复制这个功能,但我不知道该怎么做

我目前正在下载一个大型的JSON对象,我将其转换为一组NSDictionary。每个
NSDictionary
都包含关于每张照片的信息,在这些信息中,会显示一个URL。在这个URL上,我可以找到需要下载并显示在我的
UICollectionViewCells

现在,我迭代这个列表,并为我看到的每个URL启动下载。下载完成后,我使用
[self.collectionview reloadData]
重新加载collectionview。但是,正如你所能想象的,如果我有30个细胞都想要一个图像,就会有大量的
重新加载数据
调用

我正在使用AFNetworking来处理下载,下面是我根据前面提到的URL调用的方法:

-(void) downloadFeedImages:(NSString *) photoURL imageDescs:(NSDictionary*)imageDescs photoId:(NSString *)photoID{
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
    NSString *directory = [paths objectAtIndex:0];

    NSString* foofile = [directory stringByAppendingPathComponent:photoID];

    if([[NSFileManager defaultManager] fileExistsAtPath:foofile]){
        // IF IMAGE IS CACHED
        [self.collectionView reloadData];
        return;
    }

    NSLog(@"photoURL: %@", photoURL);
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:photoURL]];
    AFImageRequestOperation *operation = [AFImageRequestOperation imageRequestOperationWithRequest:request
                                                                              imageProcessingBlock:nil
                                                                                           success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
                                                                                               // Save Image
                                                                                               NSLog(@"URL-RESPONSE:%@", image);
                                                                                               NSString *myFile = [directory stringByAppendingPathComponent:photoID];

                                                                                               NSData *imageData = UIImagePNGRepresentation(image);
                                                                                               [imageData writeToFile:myFile  atomically: YES];
                                                                                               [self.collectionView reloadData];
                                                                                           }
                                                                                           failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
                                                                                               NSLog(@"ERROR: %@", [error localizedDescription]);
                                                                                           }];
    [[WebAPI sharedInstance] enqueueHTTPRequestOperation:operation];
}
因此基本上,我想知道如何实现Instagram和类似应用程序在显示带有图像的提要时所具有的功能。 此外,我想知道一种启动每个单元格下载的好方法,下载完成后,更新该单元格,而不是使用[reloadData]


谢谢

您想要实现的技术称为延迟加载。由于您使用的是
AFNetworking
,因此在您的案例中更容易实现这一点。每个集合视图单元格都需要一个
UIImageView
来显示图像。使用
UIImageView+AFNetworking.h
类别,通过调用方法设置正确的图像URL

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    // ....

    [cell.imageView setImageWithURL:imageURL placeholderImage:[UIImage imageNamed:@"placeholder.png"]];

    // ...
    return cell;
}
占位符是在下载所需图像之前将显示的图像。这将为您完成所需的工作

注意:默认情况下,URL请求的缓存策略为
NSURLCacheStorageAllowed
,超时间隔为30秒,并且设置为不处理cookies。要以不同方式配置URL请求,请使用
setImageWithURLRequest:Placeholder图像:成功:失败:

另外,为了便于参考,如果您想自己实现图像的延迟加载,请遵循以下步骤。这适用于
UITableView
,但同样的技术也可用于
UICollectionView

希望有帮助

使用

[self.collectionView reloadeitemsatindexpaths:[NSArray arrayWithObject:indexPath]]

而不是

[self.collectionView-reloadData]


这里,
indepath
是对应的
UICollectionViewCell
对象的
nsindepath
对象

使用以下方法在CellForItemIndexPath委托方法的单元格中异步加载图像

let url = URL(string: productModel.productImage)

    let data = try? Data(contentsOf: url!)
    DispatchQueue.main.async(execute: {
        collectionViewCell.imageView.image = UIImage(data: data!)
    });
在ViewController中实现协议“UICollectionViewDataSourcePrefetching”,如下所示:

类ViewController:UIViewController,UICollectionViewDataSourcePrefetching{

在序列图像板中将以下代理设置为集合视图(请参见附图) 或以编程方式

ViewController的viewDidLoad方法中


然而,当我实现这一点时,collectionview在滚动时非常有问题。这个方法完全异步吗?你知道如何使我的collectionview滚动不那么有问题吗?=)@Eyball是的,这是完全异步的。你在
cellForItemAtIndexPath
中执行的其他操作是否与FileIO类似?有操作吗可能导致主线程中出现明显停顿的设置?还有一件事,您现在不需要重新加载每个图像的集合。下载并分配图像后,AFNetworking代码将负责刷新图像视图。您可以使用相同的分类功能,该功能将首先在AFNetworking缓存中查找,如果找到,将使用se本地副本,如果没有,它将下载新副本。如果设备收到内存不足警告,则你的应用缓存目录将被删除,要求你重新下载并管理缓存。相反,让AFNetworking高效地执行此操作:)此外,AFNetworking将在缓存时处理资源刷新,例如它将检查Etag中的缓存图像。如果ovider在同一url处更改图像资源,然后AFNetworking将下载修改后的资源并替换为缓存的url。否
UICollectionViewDataSourcePrefetching
仅在iOS 10上有效+
collectionView.delegate = self
collectionView.dataSource = self
collectionView.prefetchDataSource = self