Deep analysis of the management and use of image caching in IOS applications _ios

Source: Internet
Author: User

Our IOS apps contain a lot of images. Creating attractive views relies heavily on a large number of decorative images, all of which must first be obtained from a remote server. If each open application to get each image from the server again and again, then the user experience will not achieve good results, so the local cache remote image is very necessary.

Two ways to load a local picture
1. Loading pictures by imagenamed: method
loading the picture in this way, once the picture is loaded into memory, it will not be destroyed until the program exits. (That is, imagenamed: There's a picture caching feature that's faster when you next visit the picture.) )
Loading pictures in this way, the memory management of pictures is not controlled by programmers.

Copy Code code as follows:

UIImage *image = [uiimage imagenamed: @ "image"]

To create a UIImage object, not to say that image is itself a picture, but rather that the image points to a picture. When you create this object, you do not actually load the real picture into memory, but wait until the picture is used.
As in the example above, if you set the image object to nil, if it is another object, then the object will be destroyed without a strong pointer to it, but even if image = nil, the picture resource it points to will not be destroyed.
2. Loading pictures by Imagewithcontentsoffile: Way
Using this method to load a picture, when the pointer to a picture object destroys or points to another object, the picture object does not have a strong pointer to it, and the image object is destroyed and does not remain in memory.

Because there is no caching, if the same picture is loaded more than once, there will be more than one picture object to occupy memory, not a cached picture.

Using this method, you need the full path of the file (previously used with NSString, nsarray, such as loading files are the same, such as Stringwithcontentsoffile:, see file is known to need to pass the full path. )

Copy Code code as follows:

NSString *imagepath = [[NSBundle mainbundle] pathforresource:imagename oftype:@ "PNG"];
UIImage *image = [UIImage Imagewithcontentsoffile:imagepath];

Note that this method is not available if the picture is in Images.xcassets. So you want to do your own memory management of the picture (do not want to have cached pictures), then to drag the picture resources directly into the project, rather than in the images.xcassets.


fast queues and slow queues
we set up two queues, a serial, a parallel. On the screen, the requested picture enters the parallel queue (Fastqueue), and the picture may be delayed before it enters the serial queue (Slowqueue).
In the case of the UITableView implementation, this means that the table cell on the screen gets the picture from Fastqueue, and the picture of each closed screen row is preloaded from the slowqueue.

No need to work with pictures now

Let's say we're going to request a page of information from the server that contains 30 events, and once the content has been requested, we can line up and wait for each of the graphs to be prefetch.

Copy Code code as follows:

-(void) pageLoaded: (Nsarray *) newevents {
For (Sgevent *event in newevents) {
[Sgimagecache SlowGetImageForURL:event.imageURL Thendo:nil];
}
}

Slowgetimageforurl: This method adds pictures to the Slowqueue queue, allowing them to be taken out of a sheet without blocking network traffic.
Thendo: This code block is not implemented here because we don't have to do anything with the picture at the moment. All we need to do is make sure that they are in the local disk cache and are ready to be used when sliding the table on the screen.

Now it's time to process the picture

The tables displayed on the screen want to display their pictures immediately, so they are implemented in the table cell subclass:

Copy Code code as follows:

-(void) SetEvent: (Sgevent *) Event {
__weak Sgeventcell *me = self;
[Sgimagecache GetImageForURL:event.imageURL thendo:^ (uiimage *image) {
Me.imageView.image = image; }
];
}

Getimageforurl: This method adds the process of capturing images to the fastqueue queue, meaning that they are executed in parallel as long as the iOS system allows. If the process of fetching a picture already exists in the Slowqueue queue, it is moved into the Fastqueue queue to avoid duplicate requests.

has been asynchronous

Wait, Getimageforurl: Not an asynchronous method? If you know that the picture is already in the cache, but you do not want to use it immediately on the main thread? Intuition tells you that it's wrong.
Loading pictures from disk too much resources, the same decompression of the picture also dues a lot of resources. You can configure and add tables during the slide, and the last thing you want to do when you slide a table is dangerous, because it blocks the main thread, and there's the cotton phenomenon.
Using Getimageforurl: The action that allows the disk to load is detached from the main thread, so when Thendo: the code block that is used to close the work is executed, it already has a uiimage instance, so there is no danger of sliding the cotton. If the picture already exists in the local cache, the code block that is used to close the work is executed at the next run cycle, and the user does not notice the difference between the two. What they'll notice is that the slide won't get stuck.

Now, you don't need to execute fast.

If the user quickly slides to the bottom of the table, dozens of or hundreds of table cells appear on the screen, requesting picture data from the Fastqueue, and then quickly disappearing from the screen. All of a sudden, this parallel queue is flooding the network with a lot of picture requests that are actually no longer needed. When the user finally stops sliding, the corresponding table cell view on the current screen will request their picture requests for those that are not badly needed, so the network is blocked.
This is the Wheremovetasktoslowqueueforurl: The reason for this method.

Copy Code code as follows:

A table cell is going off screen-
(void) TableView: (UITableView *) Table
Didenddisplayingcell: (UITableViewCell *) cell
Forrowatindexpath: (nsindexpath*) Indexpath {
We don ' t need it right now, so move it to the slow queue
[Sgimagecache movetasktoslowqueueforurl:[[(ID) cell event] ImageURL];
}

This ensures that only those tasks in the fastqueue that really need to be executed quickly. Any tasks previously deemed necessary for quick execution but now do not need to be moved to Slowqueue.

Focus and Choice

There are already quite a lot of iOS image cache libraries. Some of these libraries are for some scenarios only, and some libraries provide some extensibility for different scenarios. Our library is not specifically targeted at certain scenarios, nor is there a lot of all-inclusive features. For our users we have three basic types of focus:
Focus 1: the best frame rate
Many libraries are very focused on this point, using some highly customizable and complex methods, although the benchmark does not conclusively show this to be effective. We find that the best frame rate is determined by these:
The access to the disk (and almost everything else) is detached from the main thread.
Use the UIImage memory cache to avoid unnecessary disk access and image decompression.

Focus 2: Let the most important picture first show
Most libraries consider letting queue management become a concern for others. For our applications, this is almost the most important point.
Having the right picture displayed on the screen at the right time can be summed up as a simple question: "Do we need it now or after a while?" ”。 The pictures that need to be displayed immediately are in parallel loading, and everything else is added to the serial queue. All the things that were urgent before but now are not urgent will be fastqueue from the slowqueue. And when Fastqueue is working, the Slowqueue is in a suspended state.
This makes it possible for those images that need to be displayed to be able to access the network alone, while also ensuring that a picture that is not in dire need of display can become an image that needs to be displayed in a moment, because it is already in the cache and ready for display.

Point 3: API as simple as possible
most libraries do this. Many libraries provide Uiimageview classification to hide details, and many libraries make it as convenient as possible to crawl a picture of the process. For the three things we often do, our library has selected three main methods:
Catch a picture quickly

Copy Code code as follows:

__weak Sgeventcell *me = self; [Sgimagecache GetImageForURL:event.imageURL thendo:^ (uiimage *image) {me.imageView.image = image;}];

Wait in line for a picture we'll need for a while
Copy Code code as follows:

[Sgimagecache SlowGetImageForURL:event.imageURL Thendo:nil];

Notification cache a picture that needs to be displayed is no longer needed to be displayed immediately
Copy Code code as follows:

[Sgimagecache MoveTaskToSlowQueueForURL:event.imageURL];

Conclusion

By focusing on prefetching, queue management, removing time-consuming tasks from the main thread, and relying on the UIImage built-in memory cache, we strive to get good results from a simple package.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.