IOS development-Do you actually use SDWebImage?

Source: Internet
Author: User

IOS development-Do you actually use SDWebImage?
SDWebImage is currently the most popular third-party image download framework, with a high usage rate. But will you actually use it? This article will analyze how to properly use SDWebImage through examples. Use Cases: images on the custom UITableViewCell must be displayed. If the network status is WiFi, the high-definition image is displayed. If the network status is cellular mobile network, the image thumbnail is displayed. Example:

To listen to the network status, we recommend that you use AFNetWorking.
Import a third-party framework AFNetWorking to the project on GitHub or using cocoaPod. Listen to the network status in application: didfinishlaunchingwitexceptions: Method in the AppDelegate. m file.
// AppDelegate. in the m file-(BOOL) application :( UIApplication *) application didfinishlaunchingwitexceptions :( NSDictionary *) launchOptions {// monitor the network status [[AFNetworkReachabilityManager sharedManager] startMonitoring];} // The following code uses AFNetworkReachabilityManager * mgr = [AFNetworkReachabilityManager sharedManager] In the method to listen to the network status; if (mgr. isReachableViaWiFi) {// when using Wifi, download the source image} else {// others, download the thumbnail }}
At this time, iOS learners start to complain: Isn't it very easy? Therefore, the following code is completed.
// Use MVC to download the image-setItem :( CustomItem *) item {_ item = item; UIImage * placeholder = [UIImage imageNamed: @ "placeholderImage"]; AFNetworkReachabilityManager * mgr = [AFNetworkReachabilityManager sharedManager]; if (mgr. isReachableViaWiFi) {// download the source image [self. imageView sd_setImageWithURL: [NSURL URLWithString: item. originalImage] placeholderImage: placeholder];} else {// others, download the thumbnail [self. imageView sd_setImageWithURL: [NSURL URLWithString: item. thumbnailImage] placeholderImage: placeholder] ;}}

At this point, the corresponding picture can be downloaded basically according to the current network status, but it is unreasonable in actual development. Note the following:

SDWebImage will automatically help developers cache images (including memory cache and sandbox cache), so we need to set WiFiEnvironment download HD ImageNext time Cellular Network StatusThe following application should be displayed. HD ImageInstead of downloading thumbnails. Many application setting modules provide one function: HD images are still displayed in the mobile network environment. This function is actually to record the settings in the sandbox. If you want to save the data to your local computer, you can view my home article in another short book.
IOS local data access is enough here. When the user is offline, the service cannot be properly processed.

Therefore, we began to improve it. To make it easier for readers to understand, I first post the pseudocode:

-SetItem :( CustomItem *) item {_ item = item; if (the source image is cached) {self. imageView. image = source image;} else {if (Wifi environment) {download display source image} else if (mobile phone built-in Network) {if (still download source image in 3G/4G environment) {download display source image} else {download display thumbnail} else {if (Cache has thumbnail) {self. imageView. image = thumbnail;} else // process the offline status {self. imageView. image = placeholder image ;}}}}
Implement the above pseudo code: the reader can correspond to the above pseudo code one by one. Recommended during exercises Write pseudocode first, And pay more attention to writing real code. NoteDescription.
-SetItem :( CustomItem *) item {_ item = item; // placeholder image UIImage * placeholder = [UIImage imageNamed: @ "placeholderImage"]; // obtain the source image from the memory/sandbox cache. UIImage * originalImage = [[SDImageCache nvidimagecache] imageFromDiskCacheForKey: item. originalImage]; if (originalImage) {// if the source image is cached in the memory \ sandbox, the source image is directly displayed (no matter what network status it is) self. imageView. image = originalImage;} else {// memory \ sandbox cache no source image AFNetworkReachabilityManager * mgr = [AFNetworkReachabilityManager sharedManager]; if (mgr. isReachableViaWiFi) {// download the source image [self. imageView sd_setImageWithURL: [NSURL URLWithString: item. originalImage] placeholderImage: placeholder];} else if (mgr. isReachableViaWWAN) {// use the built-in network of the mobile phone. // assume that nsuserults ults is stored in the sandbox. // [[NSUserDefaults standardUserDefaults] setBool: NO forKey: @ "alwaysDownloadOriginalImage"]; // [[NSUserDefaults standardUserDefaults] synchronize]; # warning reads the user's configuration items from the sandbox: whether to download the source image BOOL alwaysDownloadOriginalImage = [[NSUserDefaults standardUserDefaults] boolForKey: @ "alwaysDownloadOriginalImage"]; if (alwaysDownloadOriginalImage) {// download the source image [self. imageView sd_setImageWithURL: [NSURL URLWithString: item. originalImage] placeholderImage: placeholder];} else {// download the thumbnail [self. imageView sd_setImageWithURL: [NSURL URLWithString: item. thumbnailImage] placeholderImage: placeholder] ;}} else {// No network UIImage * thumbnailImage = [[SDImageCache includimagecache] imageFromDiskCacheForKey: item. thumbnailImage]; if (thumbnailImage) {// memory \ sandbox cache contains the thumbnail self. imageView. image = thumbnailImage;} else {// process the offline status, and whether there is any cache self. imageView. image = placeholder ;}}}}
Solved? The real pitfalls have just begun. Before expressing the above Code, let's analyze the cache mechanism of UITableViewCell. See: There is a tableView in progress At the same timeThree uitableviewcells are displayed. tableViewCellContains a sub-Control of imageView, and each cell has Corresponding Model attributesSet the image content of the imageView. Note:: The cache pool is empty because no cell is pushed to the screen.

When a cell is pushed out of the screen, the system will automatically put the cell into the automatic cache pool.Note:: The UIImage data model corresponding to the cell is not cleared! Or point to the previous cell.

When the next cell enters the screen, the system will find the corresponding cell based on the ID registered by tableView and apply it. The cell that enters the cache pool isRepeatAdd to tableView, in the Data Source method of tableViewtableView: cellForRowAtIndexPath:CellCorresponding ModelData. In this case, the cell corresponds

The above is a brief introduction to the tableView reuse mechanism. Come back, so where is the real pitfalls mentioned above? Describe it in one scenario: when a user is in a Wi-Fi network speed Not fast enough(Images cannot be downloaded immediately). In the above Code, the large image is downloaded in a Wi-Fi environment. Therefore A certain amount of timeTo complete the download. At this time, users don't want to wait. Last openedThe image displayed when the App is in Cell below. Note: In this case, the cell image download operation is not paused and is still in the image download status.. When you are viewing Last App openedWhen the image is displayed (the image downloaded last time the App was opened, SDWebImage will help us cache the image without downloading it), and the image needs to be displayed. The image when the App was last openedThe cell uses tableView Reuse MechanismThe cell obtained from the cache pool remains in Cell aboveWhen the high-definition image has been downloaded, the default practice of SDWebImage is to immediately set the downloaded image to ImageView, so we will display the above image in the cell shown below at this time, resulting in Data disorderThis is a very serious BUG. So how can we solve this thorny problem? If we can use this cell out of the cache pool Download operationRemove, so there will be no data disorder. At this time, you may ask me: how to remove the download operation? Does the download operation help us with SDWebImage? That's right. SDWebImage helped us download images. Let's take a look at the SDWebImage source code to see how it was done.
-(Void) sd_setImageWithURL :( NSURL *) url placeholderImage :( UIImage *) placeholder options :( SDWebImageOptions) options progress :( SDWebImageDownloaderProgressBlock) progressBlock completed :( SDWebImageCompletionBlock) completedBlock {// disable the current image 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
  
   
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 injection: operation forKey: @ "UIImageViewImageLoad"];} else {callback (^ {[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 when SDWebImage downloads images, the first thing is to disable the current download operation of imageView! Are you beginning to lament how amazing SDWebImage is? That's right. We only need to set the code we wrote to directly access the local cache code using SDWebImage! The following is the complete version code.
-SetItem :( CustomItem *) item {_ item = item; // placeholder image UIImage * placeholder = [UIImage imageNamed: @ "placeholderImage"]; // obtain the original image UIImage * originalImage = [[SDImageCache nvidimagecache] imageFromDiskCacheForKey: item. originalImage]; if (originalImage) {// if the memory \ sandbox caches the source image, the source image will be displayed directly (no matter what network status it is) [self. imageView sd_setImageWithURL: [NSURL URLWithString: item. originalImage] placeholderImage: placeholder];} else {// memory \ sandbox cache no source image AFNetworkReachabilityManager * mgr = [AFNetworkReachabilityManager sharedManager]; if (mgr. isReachableViaWiFi) {// download the source image [self. imageView sd_setImageWithURL: [NSURL URLWithString: item. originalImage] placeholderImage: placeholder];} else if (mgr. isReachableViaWWAN) {// use the built-in network of the mobile phone. // assume that nsuserults ults is stored in the sandbox. // [[NSUserDefaults standardUserDefaults] setBool: NO forKey: @ "alwaysDownloadOriginalImage"]; // [[NSUserDefaults standardUserDefaults] synchronize]; # warning reads the user's configuration items from the sandbox: whether to download the source image BOOL alwaysDownloadOriginalImage = [[NSUserDefaults standardUserDefaults] boolForKey: @ "alwaysDownloadOriginalImage"]; if (alwaysDownloadOriginalImage) {// download the source image [self. imageView sd_setImageWithURL: [NSURL URLWithString: item. originalImage] placeholderImage: placeholder];} else {// download the thumbnail [self. imageView sd_setImageWithURL: [NSURL URLWithString: item. thumbnailImage] placeholderImage: placeholder] ;}} else {// No network UIImage * thumbnailImage = [[SDImageCache includimagecache] imageFromDiskCacheForKey: item. thumbnailImage]; if (thumbnailImage) {// memory \ sandbox cache contains a thumbnail [self. imageView sd_setImageWithURL: [NSURL URLWithString: item. thumbnailImage] placeholderImage: placeholder];} else {[self. imageView sd_setImageWithURL: nil placeholderImage: placeholder] ;}}}
This article introduces you here. If you have any questions or errors, please note. If you like it, just pay attention to it.

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.