简体   繁体   English

如何在iOS中加载大量图像?

[英]How to load large amount of images in iOS?

I am developing an app which displays large number of images. 我正在开发一个显示大量图像的应用程序。 when i'm loading images there's is no problem on loading of 1000 images when the image crosses the 1000 the app crashes and memory issues raised. 当我正在加载图像时,加载1000个图像时没有问题,当图像越过1000时,应用程序崩溃并引发内存问题。 How to solve it? 怎么解决? Is there any way. 有什么办法吗? Kindly help me? 请帮助我?

Thanks in Advance 提前致谢

Your app is crashing due to consuming too much memory. 由于消耗了太多内存,您的应用程序崩溃了。 So you need a strategy to manage the memory your app uses. 因此,您需要一种策略来管理应用使用的内存。

You need to set up a pooling-type system where you only load those images that might be displayed "soon". 您需要设置池化类型系统,您只需加载那些可能“很快”显示的图像。

For example, if the user is looking at image 500, you could have 498, 499, 501, and 502 loaded into memory. 例如,如果用户正在查看图像500,则可以将498,499,501和502加载到内存中。

If they move to image 501, then you deallocate 498, and load 503. 如果他们移动到图像501,则取消分配498,并加载503。

What constitutes "soon" is dependent upon how your app's flow works, but you should be able to come up with something workable. 什么构成“很快”取决于你的应用程序的流程如何工作,但你应该能够提出一些可行的东西。

You need to come up with a tableview-like system. 你需要提出一个类似tableview的系统。

If you look at them, all cells aren't loaded at the same time ; 如果你看它们,所有的细胞都不会同时加载; you can experience this if you load your app with a tableview, then put a breakpoint in cellforrow, and you'll see it being called when you start scrolling. 如果您使用tableview加载应用程序,然后在cellforrow中放置断点,您可以体验到这一点,并且当您开始滚动时,您将看到它被调用。

Because all cells aren't loaded at once. 因为所有单元格不会立即加载。

You need a similar logic with your images ; 你的图像需要类似的逻辑; you should NEVER load all of them at once. 你不应该一次加载所有这些。 And if you have a reason to, then I strongly suggest loading a thumbnail version of them ( a really low quality version of them, for a grid-like view of all your pictures, for example ). 如果你有理由,那么我强烈建议加载它们的缩略图版本(它们的质量非常低,例如,对于所有图片的网格状视图)。

To achieve that you need to know what pictures need to be immidatly visible, and what pictures are likely to be visible soon. 要实现这一目标,您需要知道哪些图片需要立即可见,以及哪些图片很快就可以看到。 For small numbers let's say you have 10 pictures total (instead of 1000). 对于小数字,假设你总共有10张图片(而不是1000张)。

User is loading the app, and can see picture 1 and 2 on the screen. 用户正在加载应用程序,可以在屏幕上看到图片1和2。 You'll obviously load them straight away, as well as picture 3 and most probably picture 4 (just to make sure). 您显然会立即加载它们,以及图片3和最可能的图片4(只是为了确保)。 When he scrolls, you KNOW that he is scrolling and your need a method that reads that scroll to allocated the right pictures dynamically. 当他滚动时,你知道他正在滚动,你需要一个方法来读取滚动以动态分配正确的图片。 You'll deallocate picture 1 first (because its the first to go away ) and start loading picture 5. 您将首先释放图片1(因为它是第一个离开)并开始加载图片5。

That way, instead of having 1000 pictures loaded, you have only up to 5 (depending on the size obviously). 这样,你只需要加载1000张图片,而不是最多5张(显然取决于尺寸)。

A really good example is the 9gag app, which loads pictures right under the screen, which means by the time you read the first gag, the next one is already loaded. 一个非常好的例子是9gag应用程序,它可以在屏幕下方加载图片,这意味着当您读取第一个插页时,下一个已加载。 The "only" way to see it load is to scroll a bit faster or to have a poor connection. 看到它加载的“唯一”方式是滚动更快或连接不良。

This logic is, to me, the most reliable and effective way to load a big amount of data, wether it is pictures or anything else. 对我来说,这种逻辑是加载大量数据的最可靠和最有效的方式,无论是图片还是其他任何东西。

Using stuff like cache, arrays, scrollview(s) and maybe files (depending on your app really) is a good starting point. 使用像缓存,数组,滚动视图和文件(真的取决于你的应用程序)之类的东西是一个很好的起点。

Probably you're getting the image-date from some API, because it's ridiculous to save it into device.. :) 可能你是从某些API获取图像日期,因为将它保存到设备中是荒谬的.. :)

My solution is to work with UITableView or UICollectionView depends on what design flow you're are choosing, because those UIComponents will manage memory for you aka will allocate the visible once + 5 down and + 5 up, and deallocate the others. 我的解决方案是使用UITableView或UICollectionView取决于你选择的设计流程,因为那些UIComponents将为你管理内存,也将分配可见的一次+5向下和+5向上,并解除分配其他。

Also you will need to download the image-date asynchronically , so you won't block the main UI - thread. 此外,您还需要异步下载图像日期,这样您就不会阻止主UI - 线程。

Now... if i were you, I'll definitely go for third party library such as AFNetworking in your case, its best for handling JSON data from server, also have very good error handling. 现在......如果我是你,我肯定会去你的第三方库,比如AFNetworking ,它最适合处理来自服务器的JSON数据,也有非常好的错误处理。

Here I'll post a method witch is for downloading image-data from server. 在这里,我将发布一个方法,用于从服务器下载图像数据。

- (void)downloadImageAsynchronicallyByUrlString:(NSString *)url forIndexPath:(NSIndexPath *)indexPath {
    // Perofrm request
    AFHTTPRequestOperation *requestOperation = [[AFHTTPRequestOperation alloc]initWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:url]]];
    [requestOperation setResponseSerializer:[AFImageResponseSerializer serializer]];
    [requestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {

        // IF SUCCSESS send dataSource SUCCSESS message
        [dataSource downloadFinished:responseObject forIndexPath:indexPath];

    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {

        // IF FAIL send dataSource FAIL message
        [dataSource downloadFailAtIndexPath:indexPath];
    }];

    // Start request!!!
    [requestOperation start];
}

Explanation: 说明:

You call every time this method in cellForRowAtIndexPath at your tableView or itemForRowAtIndexPath if you use collectionView and I'm using a protocol to handle when responseObject aka theImage to send the responseObject via protocol method. 你在tableView或itemForRowAtIndexPath中的每个时候在cellForRowAtIndexPath中调用这个方法,如果你使用collectionView并且我使用协议来处理当responseObject也通过协议方法发送responseObject的图像时。

In your UIClass where your tableView pr collectionView lives just implement your protocol method 在你的tableView pr collectionView所在的UIClass中,只需实现你的协议方法

- (void)downloadFinished:(UIImage *)image forIndexPath:(NSIndexPath *)indexPath {

    // Creating copy of cell
    _lecturerCell = (LecturersCell *)[_lecturersTableView cellForRowAtIndexPath:indexPath];
    // Set downloaded image
    [_lecturerCell setLecturerImage:image];
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM