Ios-sdwebimage loading pictures based on network status

Source: Internet
Author: User

iOS development-Do you really use sdwebimage?2016-05-17 Hosea_zhou interesting.

Original Hosea_zhou

Original address:
http://www.jianshu.com/p/dabc0c6d083e

Ape Bar-Resource Sharing forum:

http://www.coderbar.cn

Recently, the forum has the latest video materials Oh!

Sdwebimage as the most popular image download third-party framework, the use rate is very high. But are you really going to use it? This article will then take an example to analyze how to use sdwebimage rationally.

Use the scene: The custom UITableViewCell has the picture need to display, requires the network status is WiFi, displays the picture high definition image, when the network status is cellular network, displays the picture thumbnail. As an example:

The picture shown in the image conforms to the network status download request

In order to listen to the network status, here I recommend the use of afnetworking.

    1. Import a third-party framework afnetworking on GitHub or use Cocoapod for the project.

    2. Listen for network status in the Application:didfinishlaunchingwithoptions: method in the APPDELEGATE.M file.

In the APPDELEGATE.M file

-(BOOL) Application: (UIApplication *) application didfinishlaunchingwithoptions: (nsdictionary *) launchOptions

{

Monitor network status

[[Afnetworkreachabilitymanager Sharedmanager] startmonitoring];

}

The following code is used in methods that need to listen for network state

Afnetworkreachabilitymanager *mgr = [Afnetworkreachabilitymanager Sharedmanager];

if (Mgr.isreachableviawifi) {//When using WiFi, download the original

} else {//others, download small image

}

}

    • Then there will be an iOS learner complaining: Isn't that easy? So rinsed finished writing the following code.

Using MVC, when setting the cell's model properties, download the image

-SetItem: (Customitem *) Item

{

_item = Item;

UIImage *placeholder = [UIImage imagenamed:@ "Placeholderimage"];

Afnetworkreachabilitymanager *mgr = [Afnetworkreachabilitymanager Sharedmanager];

if (Mgr.isreachableviawifi) {//When using WiFi, download the original

[Self.imageview Sd_setimagewithurl:[nsurl URLWithString:item.originalImage] placeholderimage:placeholder];

} else {//others, download small image

[Self.imageview Sd_setimagewithurl:[nsurl URLWithString:item.thumbnailImage] placeholderimage:placeholder];

}

}

    • At this point, it is really possible to complete the basic download the corresponding image according to the current network status, but in real development, this is actually unreasonable. Here are some details to keep in mind:

    1. Sdwebimage will automatically help developers to cache images (including memory cache, sandbox cache), so we need to set up the user in the WiFi environment download high-definition images, the next time in the cellular network state to open the app should also display high-definition images, rather than to download thumbnails.

    2. Many application settings modules come with a feature: HD images are still displayed in the mobile network environment. This feature is actually set record in the sandbox, about the data saved to the local, you can view my other brief book home article

    3. iOS local data access, see here is enough

    4. The business cannot be handled properly when the user is offline.

    • So, we started to improve. To make it easier for the reader to understand, I'll post the pseudocode:

-SetItem: (Customitem *) Item

{

_item = Item;

If (the original is in the cache)

{

Self.imageView.image = original;

} else

{

if (WiFi environment)

{

Download Display Original

} else if (phone comes with network)

{

if (still download the original image under 3G\4G environment)

{

Download Display Original

} else

{

Download Show small image

}

} else

{

If (there is a small image in the cache)

{

Self.imageView.image = Small map;

} else//processing offline status

{

Self.imageView.image = placeholder picture;

}

}

}

}

    • Implement the above pseudo-code: The reader can correspond to the above pseudo-code. In practice, it is recommended to write the pseudocode first and then write the real code.

    • A lot of attention to annotation explanation.

-SetItem: (Customitem *) Item

{

_item = Item;

Placeholder Pictures

UIImage *placeholder = [UIImage imagenamed:@ "Placeholderimage"];

Get the original image from the memory \ Sandbox cache,

UIImage *originalimage = [[Sdimagecache Sharedimagecache] imageFromDiskCacheForKey:item.originalImage];

if (originalimage) {//if the memory \ Sandbox cache has an original image, then the original image is displayed directly (no matter what network status is present)

Self.imageView.image = Originalimage;

} else {//memory \ Sandbox cache has no original

Afnetworkreachabilitymanager *mgr = [Afnetworkreachabilitymanager Sharedmanager];

if (Mgr.isreachableviawifi) {//When using WiFi, download the original

[Self.imageview Sd_setimagewithurl:[nsurl URLWithString:item.originalImage] placeholderimage:placeholder];

} else if (Mgr.isreachableviawwan) {//in using the phone to bring your own network

User's configuration items are assumed to be stored in a sandbox using nsuserdefaults

[[Nsuserdefaults Standarduserdefaults] setbool:no forkey:@ "Alwaysdownloadoriginalimage"];

[[Nsuserdefaults standarduserdefaults] synchronize];

#warning read the user's configuration items from the sandbox: whether the original image is still downloaded in the 3G\4G environment

BOOL alwaysdownloadoriginalimage = [[Nsuserdefaults standarduserdefaults] boolforkey:@ "Alwaysdownloadoriginalimage" ];

if (alwaysdownloadoriginalimage) {//download original

[Self.imageview Sd_setimagewithurl:[nsurl URLWithString:item.originalImage] placeholderimage:placeholder];

} else {//download small image

[Self.imageview Sd_setimagewithurl:[nsurl URLWithString:item.thumbnailImage] placeholderimage:placeholder];

}

} else {//no network

UIImage *thumbnailimage = [[Sdimagecache Sharedimagecache] imageFromDiskCacheForKey:item.thumbnailImage];

if (thumbnailimage) {//memory \ Sandbox cache has a small image

Self.imageView.image = thumbnailimage;

} else {//handles offline status, and there is no cache condition

Self.imageView.image = placeholder;

}

}

}

}

Has it been solved? The real pit is only just beginning.

    • Before we describe the hole in the code above, let's analyze the caching mechanism of UITableViewCell.

    • See: There is a tableview is displaying three uitableviewcell at the same time, each Tableviewcell contains a ImageView child control, and each cell has a corresponding model property to set the contents of the ImageView picture.

    • Note: The cache pool is empty because no cell is pushed out of the screen.


Cell has not been pushed into the cache pool

    • When a cell is pushed out of the screen, the cell is automatically placed in the automatic cache pool. Note: The cell's uiimage image data model is not emptied! Or a cell that is used up.


Cell is put into the cache pool

    • When the next cell enters the screen, the system will find the corresponding cell according to the logo registered by TableView, and apply it. The cells entered into the buffer pool are re-added to the TableView, and the data source method in TableView Tableview:cellforrowatindexpath: sets the corresponding model of the cell


Cell is put into the cache pool

    • The above is a brief introduction to the TableView reuse mechanism.

Back again, so where is the real pit above?

    • Use a scene to describe it: when the user's environment WiFi speed is not fast enough (can not immediately download the picture completed), and in the above code, in the WiFi environment is also downloaded high-definition large image. So it takes a certain amount of time to complete the download. At this point, users do not want to wait to see the last time the app was opened to show the picture, the user will slide to the following cell to view. Note: At this point, the above cell download picture operation is not paused and is still in the download picture state. When the user views the last Open app's display picture (the last time you open the app download completed picture, Sdwebimage will help us cache, not download), And just need to show the last time the app opened the image of the cell is the use of tableview reuse mechanism from the buffer pool from the cell, wait until the above cell in the high-definition large image has been downloaded, sdwebimage default practice is, Immediately set the downloaded image to ImageView, so we will be at the bottom of the displayed cell display above the image, causing data confusion, this is a very serious bug.

So how do you solve this thorny problem?

    • If we were able to remove the cell before it was put in the cache pool when it was taken out of the cache pool, there would be no data confusion.

    • At this point you may ask me: How do I remove the download operation? Download operation is not sdwebimage to help us do it?

    • That's right, it is sdwebimage to help us download pictures, we have to grilled a Sdwebimage source code to see how he was completed.

-(void) Sd_setimagewithurl: (nsurl *) URL placeholderimage: (UIImage *) placeholder options: (sdwebimageoptions) options Progress: (Sdwebimagedownloaderprogressblock) Progressblock completed: (sdwebimagecompletionblock) CompletedBlock {

Close the current picture download operation

[Self sd_cancelcurrentimageload];

Objc_setassociatedobject (self, &imageurlkey, url, objc_association_retain_nonatomic);

if (! ( Options & Sdwebimagedelayplaceholder)) {

Dispatch_main_async_safe (^{

Self.image = placeholder;

});

}

if (URL) {

Check if ActivityView is enabled or not

if ([self showactivityindicatorview]) {

[Self addactivityindicator];

}

__weak __typeof (self) wself = self;

ID <SDWebImageOperation> operation = [Sdwebimagemanager.sharedmanager downloadimagewithurl:url options:options Progress:progressblock completed:^ (UIImage *image, Nserror *error, Sdimagecachetype CacheType, BOOL finished, NSURL * ImageURL) {

[Wself Removeactivityindicator];

if (!wself) return;

Dispatch_main_sync_safe (^{

if (!wself) return;

if (Image && options & sdwebimageavoidautosetimage) && Completedblock)

{

Completedblock (image, error, cachetype, URL);

Return

}

else if (image) {

Wself.image = image;

[Wself Setneedslayout];

} else {

if (options & Sdwebimagedelayplaceholder) {

Wself.image = placeholder;

[Wself Setneedslayout];

}

}

if (Completedblock && finished) {

Completedblock (image, error, cachetype, URL);

}

});

}];

[Self sd_setimageloadoperation:operation forkey:@ "uiimageviewimageload"];

} else {

Dispatch_main_async_safe (^{

[Self removeactivityindicator];

if (Completedblock) {

Nserror *error = [Nserror errorwithdomain:sdwebimageerrordomain code:-1 Userinfo:@{nslocalizeddescriptionkey: @ " Trying to load a nil url "}";

Completedblock (nil, error, sdimagecachetypenone, URL);

}

});

}

}

We are surprised to find that the original sdwebimage when downloading pictures, the first thing is to close imageview current download operation!

    • Does it start to sigh sdwebimage how magical? Yes, we just have to write the code we wrote all the direct access to the local cache code using Sdwebimage to set it OK!

    • Here is the complete version of the code.

-SetItem: (Customitem *) Item

{

_item = Item;

Placeholder Pictures

UIImage *placeholder = [UIImage imagenamed:@ "Placeholderimage"];

Get the original image from memory \ Sandbox cache

UIImage *originalimage = [[Sdimagecache Sharedimagecache] imageFromDiskCacheForKey:item.originalImage];

if (originalimage) {//if the memory \ Sandbox cache has an original image, then the original image is displayed directly (no matter what network status is present)

[Self.imageview Sd_setimagewithurl:[nsurl URLWithString:item.originalImage] placeholderimage:placeholder];

} else {//memory \ Sandbox cache has no original

Afnetworkreachabilitymanager *mgr = [Afnetworkreachabilitymanager Sharedmanager];

if (Mgr.isreachableviawifi) {//When using WiFi, download the original

[Self.imageview Sd_setimagewithurl:[nsurl URLWithString:item.originalImage] placeholderimage:placeholder];

} else if (Mgr.isreachableviawwan) {//in using the phone to bring your own network

User's configuration items are assumed to be stored in a sandbox using nsuserdefaults

[[Nsuserdefaults Standarduserdefaults] setbool:no forkey:@ "Alwaysdownloadoriginalimage"];

[[Nsuserdefaults standarduserdefaults] synchronize];

#warning read the user's configuration items from the sandbox: whether the original image is still downloaded in the 3G\4G environment

BOOL alwaysdownloadoriginalimage = [[Nsuserdefaults standarduserdefaults] boolforkey:@ "Alwaysdownloadoriginalimage" ];

if (alwaysdownloadoriginalimage) {//download original

[Self.imageview Sd_setimagewithurl:[nsurl URLWithString:item.originalImage] placeholderimage:placeholder];

} else {//download small image

[Self.imageview Sd_setimagewithurl:[nsurl URLWithString:item.thumbnailImage] placeholderimage:placeholder];

}

} else {//no network

UIImage *thumbnailimage = [[Sdimagecache Sharedimagecache] imageFromDiskCacheForKey:item.thumbnailImage];

if (thumbnailimage) {//memory \ Sandbox cache has a small image

[Self.imageview Sd_setimagewithurl:[nsurl URLWithString:item.thumbnailImage] placeholderimage:placeholder];

} else {

[Self.imageview Sd_setimagewithurl:nil Placeholderimage:placeholder];

}

}

}

}

This article describes here, if you have any questions or errors, you are welcome to point out. Like just a little attention to it.

Ios-sdwebimage loading pictures based on network status

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.