iOS tutorials, iOS dry has been too late for everyone to share, the small part is also always busy Ah! Today, we offer iOS: A detailed explanation of the caching mechanism of iOS multi-image download
1. What is the demand point?
The multi-image download Here is to display a picture in every cell in TableView, and these images need to be downloaded from the Internet.
2. Easy-to-encounter problems
If you do not know or use asynchronous operations and caching mechanisms, it is likely that the code is written like this:
Cell.textLabel.text = App.name;
Cell.detailTextLabel.text = App.download; NSData *imagedata = [NSData DataWithContentsOfURL:app.url];
Cell.imageView.image = [UIImage imagewithdata:imagedata];
What is the consequence of this writing?
Consequence 1: unavoidable lag (because there is no asynchronous download operation)
Datawithcontentsofurl: is a time-consuming operation, placing it on the main thread will cause the Dayton. If the picture is many, the picture is very big, and the network condition is not good, certainly will be stuck!
Consequence 2: Duplicate download of the same picture, consuming traffic and overhead (because no caching mechanism is established)
Because there is no caching mechanism, even though the download is complete and the current cell's picture is displayed, the cell will download its corresponding picture when it needs to be displayed again: it consumes download traffic and causes repeated operations.
Obviously, to achieve tableview rolling, such as silky-like enjoyment must be both, how to do it?
3. Solution
1. First look at the flowchart of the solution
650) this.width=650; "src=" Http://www.cdtedu.com/uploads/allimg/160930/1-160930104055D6.png "alt=" Training "style=" border:0px; "/>
To get a quick look at this diagram, you need to understand all the data sources that the process requires:
1. URL of the picture: Because each image corresponds to the URL is unique, so we can create the image cache and download operation of the cache key, as well as stitching the path string of the sandbox cache.
2. Picture cache (Dictionary): stored in memory, key is the URL of the picture, the value is UIImage object. Function: Fast reading speed, direct use of UIImage object.
3. Download operation cache (dictionary): Store with memory, key is the URL of the picture, the value is Nsblockoperation object. Role: To avoid opening multiple download threads for the same picture.
4. Sandbox cache (file path corresponds to NSData): stored on disk, located in the Cache folder, the path is "cache/the last part of picture url", the value is NSData object (convert UIImage to NSData to write to disk). Function: The program breaks the net, start again can also get the picture directly on the disk.
2. Another look at the code for the solution
2.1 Image cache, download operation cache, sandbox cache path
/**
* Store all downloaded images
*/@property (nonatomic, strong) Nsmutabledictionary *images;/**
* Store all download operations (key is Url,value is Operation object)
*/@property (nonatomic, strong) Nsmutabledictionary *operations;/**
* The path of the Mosaic cache folder and the last part of the URL, merged into a unique agreed cache path
*/#define CACHEDIMAGEFILE (URL) [[Nssearchpathfordirectoriesindomains (Nscachesdirectory, Nsuserdomainmask, YES) Lastobject] Stringbyappendingpathcomponent:[url Lastpathcomponent]]
2.2 Images before downloading the query cache section:
The uiimage of the image URL is taken from the images cache first
UIImage *image = Self.images[app.icon]; if (image) {//exists: The description picture has been downloaded successfully and the cache is successful)
Cell.imageView.image = image;
} else {//does not exist: The description picture has not been downloaded successfully, or successfully downloaded but the cache failed in images, need to look for the picture in the sandbox
Get the URL for the sandbox cache path
NSString *file = Cachedimagefile (App.icon); First take the picture out of the sandbox
NSData *data = [NSData datawithcontentsoffile:file]; if (data) {//data is not empty, it indicates that the file exists in the sandbox
Cell.imageView.image = [UIImage imagewithdata:data];
} else {//vice versa, this file does not exist in the sandbox
Show placeholder pictures before downloading
Cell.imageView.image = [UIImage imagenamed:@ "placeholder"];//download picture
[Self Download:app.icon indexpath:indexpath];
}
}
2.3 Download part of the picture:
/**
* Download Image
* @param URL of imageUrl picture
*/-(void) Download: (NSString *) imageUrl Indexpath: (Nsindexpath *) Indexpath
{//Remove the download action for the current picture URL (Operation object)
Nsblockoperation *operation = Self.operations[imageurl]; if (operation) return; Create an action, download a picture
__weak typeof (self) appsvc = self;
Operation = [Nsblockoperation blockoperationwithblock:^{nsurl *url = [Nsurl Urlwithstring:imageurl]; NSData *data = [NSData datawithcontentsofurl:url];//download
UIImage *image = [UIImage imagewithdata:data]; NSData-UIImage
Back to main thread
[[Nsoperationqueue Mainqueue] addoperationwithblock:^{if (image) {//If a picture is present (download complete), the picture is stored in the picture cache dictionary
Appsvc.images[imageurl] = image; Save the picture in a sandbox
1. First convert the picture to NSData
NSData *data = uiimagepngrepresentation (image); 2. To generate the cache path again
[Data Writetofile:cachedimagefile (IMAGEURL) Atomically:yes];
}//Remove the download from the dictionary (to ensure that the download fails and can be downloaded again)
[Appsvc.operations Removeobjectforkey:imageurl]; Refresh the current table to reduce system overhead
[Appsvc.tableview reloadrowsatindexpaths:@ [Indexpath] withrowanimation:uitableviewrowanimationnone];
}];
}]; Add a download operation to the queue
[Self.queue addoperation:operation]; Add the current download operation to the download operation cache (in order to resolve a duplicate download)
Self.operations[imageurl] = operation;
}
3. What are the points that are noteworthy?
It is important to note that the addition and deletion of cached content is still indispensable.
3.1 About picture caching:
Very simple, successful download, get the picture, the image is added to the image cache; Download failed, nothing to do, anyway, no diagram. In this mechanism, there is no deletion of the cache in the case of an image item, because the picture cache will never be repeated to add more than one picture of the case, the cache as long as there is a corresponding diagram, directly taken to use, will not be downloaded again.
3.2 About the sandbox cache:
Similarly, the sandbox cache is also a reason: there is a diagram to convert it to NSData, write to disk, and corresponding to the unique path, no diagram is not written. So even if you want to download the same picture, because the current URL corresponding to the sandbox path already exists file, so directly take it, will not be downloaded.
But!
The download operation cache is different!
3.3 About the download operation cache
We need to delete the current download operation from the download operation cache immediately after the download callback is complete!
Because you want to avoid the download failure after the situation can not be downloaded again!
Why is it?
Note the time to add the download operation to the download operation cache:
It was at the beginning of the download and not the moment the download was successful!
If added to the cache at the start of the download, this cache includes two scenarios: Download success and download failure:
If the future download succeeds, then we will not come to determine whether the current download operation in the download operation cache This step, before this directly can take the diagram to use, download operation is not in the download operation cache is not any effect.
However, if the future download fails, then there will be no corresponding image cache and sandbox cache, it will certainly come to determine whether the current download operation in the download operation cache this step. Unfortunately, it is there because it has not been deleted. If there is nothing else to do, letting go, the pictures that have failed to download will never be downloaded again.
Did you forget the code? Look back at the code (see how good I am):
Nsblockoperation *operation = Self.operations[imageurl]; if (operation) return;//turned and walked, relentlessly
Therefore, whether the download succeeds or fails, the current download operation is removed from the download operation queue in the image download callback: To ensure that if the download fails, you can re-open the corresponding download
The operation is downloaded and logically more rigorous.
4. Last Words
The two mechanisms of asynchronous + caching will make a big difference to the new program. This should be the only way to develop advanced apps.
Small size brother told the process is relatively complete, more important is to learn the idea:
Cache Rating: Memory cache, sandbox cache, download operation cache.
And we have to use the dichotomy often, to take our logic into account.
If we do not realize that the time to add the download operation to the download operation cache is to include both the download success and the download failure, we will not take into account the immediate deletion of the download operation from the download operation cache, which can easily cause a bug. So in the future development, both success and failure should be taken into account, that is, if there must be else!
iOS Tutorial: Detailed caching mechanism for iOS multi-image downloads