zoukankan      html  css  js  c++  java
  • SDWebImage源码探究(四)

    UIImageView+normal 下载图片

      这个应该是SDWebImage的最基本的使用了,就是利用给定的URL下载图片,采用的是UIImageView的分类webcache.

    代码:

    #import "JJWebImageVC.h"
    #import "Masonry.h"
    #import "UIImageView+WebCache.h"
    
    @interface JJWebImageVC ()
    
    @property (nonatomic, strong) UIImageView *imageView;
    
    
    @end
    
    @implementation JJWebImageVC
    
    #pragma mark - Override Base Function
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        
        self.view.backgroundColor = [UIColor lightGrayColor];
        
        [self setupUI];
        
        [self loadData];
    }
    
    #pragma mark - Object Private Function
    
    - (void)setupUI
    {
        UIImageView *imageView = [[UIImageView alloc] init];
        [self.view addSubview:imageView];
        self.imageView = imageView;
        
        [imageView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.center.equalTo(self.view);
            make.height.width.equalTo(@200);
        }];
    }
    
    - (void)loadData
    {
        [self.imageView sd_setImageWithURL:[NSURL URLWithString:@"http://picture.51rebo.cn/149991503036592"] placeholderImage:[UIImage imageNamed:@"placeholder"]];
    }
    
    @end

    图片下载除了上面这个方法还有下面几个方法

    - (void)sd_setImageWithURL:(nullable NSURL *)url
              placeholderImage:(nullable UIImage *)placeholder
                       options:(SDWebImageOptions)options;
    
    - (void)sd_setImageWithURL:(nullable NSURL *)url
              placeholderImage:(nullable UIImage *)placeholder
                     completed:(nullable SDExternalCompletionBlock)completedBlock;
    
    - (void)sd_setImageWithURL:(nullable NSURL *)url
              placeholderImage:(nullable UIImage *)placeholder
                       options:(SDWebImageOptions)options
                     completed:(nullable SDExternalCompletionBlock)completedBlock;
    
    - (void)sd_setImageWithURL:(nullable NSURL *)url
              placeholderImage:(nullable UIImage *)placeholder
                       options:(SDWebImageOptions)options
                      progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
                     completed:(nullable SDExternalCompletionBlock)completedBlock;

    这里最后面这个方法的参数是最多的,达到了5个,多的不说了,主要说一下progress这个是下载进度的回调,completed下载完成的block,options这个参数是最重要的,是一个枚举值,主要对下载图片的情况进行配置,下面我们就看一下这个枚举值。

    typedef NS_OPTIONS(NSUInteger, SDWebImageOptions) {
        /**
         * By default, when a URL fail to be downloaded, the URL is blacklisted so the library won't keep trying.
         * This flag disable this blacklisting.
         */
        //默认的情况下,当一个URL下载失败了,那么这个URL会被放在黑名单里面,不会继续尝试,这个标志位就是使黑名单效果失效,保证失败后可以重新尝试。
        SDWebImageRetryFailed = 1 << 0,
    
        /**
         * By default, image downloads are started during UI interactions, this flags disable this feature,
         * leading to delayed download on UIScrollView deceleration for instance.
         */
        //默认情况下,在UI交互的情况下就开始图像下载,该标志位使该特性失效,例如在UIScrollView减速时延迟下载。
        SDWebImageLowPriority = 1 << 1,
    
        /**
         * This flag disables on-disk caching
         */
        //该标志位使磁盘缓存失效,只是内存缓存。
        SDWebImageCacheMemoryOnly = 1 << 2,
    
        /**
         * This flag enables progressive download, the image is displayed progressively during download as a browser would do.
         * By default, the image is only displayed once completely downloaded.
         */
        //该标志位可以确保下载的回调,图像可以边下载边显示
        SDWebImageProgressiveDownload = 1 << 3,
    
        /**
         * Even if the image is cached, respect the HTTP response cache control, and refresh the image from remote location if needed.
         * The disk caching will be handled by NSURLCache instead of SDWebImage leading to slight performance degradation.
         * This option helps deal with images changing behind the same request URL, e.g. Facebook graph api profile pics.
         * If a cached image is refreshed, the completion block is called once with the cached image and again with the final image.
         *
         * Use this flag only if you can't make your URLs static with embedded cache busting parameter.
         */
        //刷新缓存
        SDWebImageRefreshCached = 1 << 4,
    
        /**
         * In iOS 4+, continue the download of the image if the app goes to background. This is achieved by asking the system for
         * extra time in background to let the request finish. If the background task expires the operation will be cancelled.
         */
        //后台下载
        SDWebImageContinueInBackground = 1 << 5,
    
        /**
         * Handles cookies stored in NSHTTPCookieStore by setting
         * NSMutableURLRequest.HTTPShouldHandleCookies = YES;
         */
        //处理NSHTTPCookieStore中存储的cookie
        SDWebImageHandleCookies = 1 << 6,
    
        /**
         * Enable to allow untrusted SSL certificates.
         * Useful for testing purposes. Use with caution in production.
         */
          //允许使用无效的SSL整数,但是仅用于测试,生产环境要小心
        SDWebImageAllowInvalidSSLCertificates = 1 << 7,
    
        /**
         * By default, images are loaded in the order in which they were queued. This flag moves them to
         * the front of the queue.
         */
        //默认的情况,图像下载都是按照队列内部的顺序进行的,这个标志位就是提高优先级,让其移动到队列的首位。
        SDWebImageHighPriority = 1 << 8,
        
        /**
         * By default, placeholder images are loaded while the image is loading. This flag will delay the loading
         * of the placeholder image until after the image has finished loading.
         */
        //默认的情况下是占位图在下载图像的时候加载,这个标志位延迟占位图的加载,直到图像下载完成。
        SDWebImageDelayPlaceholder = 1 << 9,
    
        /**
         * We usually don't call transformDownloadedImage delegate method on animated images,
         * as most transformation code would mangle it.
         * Use this flag to transform them anyway.
         */
        //我们一般不调用transformDownloadedImage代理方法处理动画图片,因为大多数的转换代码会损坏它,使用这个标志位可以转换它们。
        SDWebImageTransformAnimatedImage = 1 << 10,
        
        /**
         * By default, image is added to the imageView after download. But in some cases, we want to
         * have the hand before setting the image (apply a filter or add it with cross-fade animation for instance)
         * Use this flag if you want to manually set the image in the completion when success
         */
        //默认情况下,图像在下载完成后都是加载到UIImageview上,但是在一些情况下,我们想要在设置图像之前处理它,比如说加一个滤镜或者褪色的动画效果等等,使用这个标志位,如果你想要手动的在成功完成回调后设置这个图片。
        SDWebImageAvoidAutoSetImage = 1 << 11,
        
        /**
         * By default, images are decoded respecting their original size. On iOS, this flag will scale down the
         * images to a size compatible with the constrained memory of devices.
         * If `SDWebImageProgressiveDownload` flag is set the scale down is deactivated.
         */
        //默认情况下,图像都是根据他们原始尺寸进行解码,在ios中,这个标志位会缩小图片,以便能够兼容器件内存的限制,如果SDWebImageProgressiveDownload被设置了,那么这个位就失效了。
        SDWebImageScaleDownLargeImages = 1 << 12
    };

    UIImageView+highlightedImage图片下载

    这个方法也是UIImageView的分类,专门用来下载highlightedImage。调用的是下面这个方法。

    - (void)sd_setHighlightedImageWithURL:(nullable NSURL *)url
                                  options:(SDWebImageOptions)options
                                 progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
                                completed:(nullable SDExternalCompletionBlock)completedBlock;
    - (void)sd_internalSetImageWithURL:(nullable NSURL *)url
                      placeholderImage:(nullable UIImage *)placeholder
                               options:(SDWebImageOptions)options
                          operationKey:(nullable NSString *)operationKey
                         setImageBlock:(nullable SDSetImageBlock)setImageBlock
                              progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock
                             completed:(nullable SDExternalCompletionBlock)completedBlock;

    判断是否是gif图

    这个要根据UIImage的一个分类UIImage+GIF进行判断。UIImage对象有一个属性如下:

    @property(nullable, nonatomic,readonly) NSArray<UIImage *> *images   NS_AVAILABLE_IOS(5_0); // default is nil for non-animated images

    根据NSData创建动画的图像

    这个方法也在分类UIImage+GIF里面,如下所示。

    /**
     *  Compatibility method - creates an animated UIImage from an NSData, it will only contain the 1st frame image
     */
    + (UIImage *)sd_animatedGIFWithData:(NSData *)data;

    UIButton设置图像

    该框架也提供了UIButton设置图像的方法,以及设置背景图像的方法,还有就是取消的方法,下面我们接着看。

    1.设置图像的方法

    #pragma mark - Image
    
    /**
     * Get the image URL for a control state.
     * 
     * @param state Which state you want to know the URL for. The values are described in UIControlState.
     */
    - (nullable NSURL *)sd_imageURLForState:(UIControlState)state;
    
    /**
     * Set the imageView `image` with an `url`.
     *
     * The download is asynchronous and cached.
     *
     * @param url   The url for the image.
     * @param state The state that uses the specified title. The values are described in UIControlState.
     */
    - (void)sd_setImageWithURL:(nullable NSURL *)url
                      forState:(UIControlState)state;
    
    /**
     * Set the imageView `image` with an `url` and a placeholder.
     *
     * The download is asynchronous and cached.
     *
     * @param url         The url for the image.
     * @param state       The state that uses the specified title. The values are described in UIControlState.
     * @param placeholder The image to be set initially, until the image request finishes.
     * @see sd_setImageWithURL:placeholderImage:options:
     */
    - (void)sd_setImageWithURL:(nullable NSURL *)url
                      forState:(UIControlState)state
              placeholderImage:(nullable UIImage *)placeholder;
    
    /**
     * Set the imageView `image` with an `url`, placeholder and custom options.
     *
     * The download is asynchronous and cached.
     *
     * @param url         The url for the image.
     * @param state       The state that uses the specified title. The values are described in UIControlState.
     * @param placeholder The image to be set initially, until the image request finishes.
     * @param options     The options to use when downloading the image. @see SDWebImageOptions for the possible values.
     */
    - (void)sd_setImageWithURL:(nullable NSURL *)url
                      forState:(UIControlState)state
              placeholderImage:(nullable UIImage *)placeholder
                       options:(SDWebImageOptions)options;
    
    /**
     * Set the imageView `image` with an `url`.
     *
     * The download is asynchronous and cached.
     *
     * @param url            The url for the image.
     * @param state          The state that uses the specified title. The values are described in UIControlState.
     * @param completedBlock A block called when operation has been completed. This block has no return value
     *                       and takes the requested UIImage as first parameter. In case of error the image parameter
     *                       is nil and the second parameter may contain an NSError. The third parameter is a Boolean
     *                       indicating if the image was retrieved from the local cache or from the network.
     *                       The fourth parameter is the original image url.
     */
    - (void)sd_setImageWithURL:(nullable NSURL *)url
                      forState:(UIControlState)state
                     completed:(nullable SDExternalCompletionBlock)completedBlock;
    
    /**
     * Set the imageView `image` with an `url`, placeholder.
     *
     * The download is asynchronous and cached.
     *
     * @param url            The url for the image.
     * @param state          The state that uses the specified title. The values are described in UIControlState.
     * @param placeholder    The image to be set initially, until the image request finishes.
     * @param completedBlock A block called when operation has been completed. This block has no return value
     *                       and takes the requested UIImage as first parameter. In case of error the image parameter
     *                       is nil and the second parameter may contain an NSError. The third parameter is a Boolean
     *                       indicating if the image was retrieved from the local cache or from the network.
     *                       The fourth parameter is the original image url.
     */
    - (void)sd_setImageWithURL:(nullable NSURL *)url
                      forState:(UIControlState)state
              placeholderImage:(nullable UIImage *)placeholder
                     completed:(nullable SDExternalCompletionBlock)completedBlock;
    
    /**
     * Set the imageView `image` with an `url`, placeholder and custom options.
     *
     * The download is asynchronous and cached.
     *
     * @param url            The url for the image.
     * @param state          The state that uses the specified title. The values are described in UIControlState.
     * @param placeholder    The image to be set initially, until the image request finishes.
     * @param options        The options to use when downloading the image. @see SDWebImageOptions for the possible values.
     * @param completedBlock A block called when operation has been completed. This block has no return value
     *                       and takes the requested UIImage as first parameter. In case of error the image parameter
     *                       is nil and the second parameter may contain an NSError. The third parameter is a Boolean
     *                       indicating if the image was retrieved from the local cache or from the network.
     *                       The fourth parameter is the original image url.
     */
    - (void)sd_setImageWithURL:(nullable NSURL *)url
                      forState:(UIControlState)state
              placeholderImage:(nullable UIImage *)placeholder
                       options:(SDWebImageOptions)options
                     completed:(nullable SDExternalCompletionBlock)completedBlock;

    2.获取按钮图像的URL

    /**
     * Get the current image URL.
     */
    - (nullable NSURL *)sd_currentImageURL;

    3、获取按钮背景backgroundImage

    #pragma mark - Background image
    
    /**
     * Set the backgroundImageView `image` with an `url`.
     *
     * The download is asynchronous and cached.
     *
     * @param url   The url for the image.
     * @param state The state that uses the specified title. The values are described in UIControlState.
     */
    - (void)sd_setBackgroundImageWithURL:(nullable NSURL *)url
                                forState:(UIControlState)state;
    
    /**
     * Set the backgroundImageView `image` with an `url` and a placeholder.
     *
     * The download is asynchronous and cached.
     *
     * @param url         The url for the image.
     * @param state       The state that uses the specified title. The values are described in UIControlState.
     * @param placeholder The image to be set initially, until the image request finishes.
     * @see sd_setImageWithURL:placeholderImage:options:
     */
    - (void)sd_setBackgroundImageWithURL:(nullable NSURL *)url
                                forState:(UIControlState)state
                        placeholderImage:(nullable UIImage *)placeholder;
    
    /**
     * Set the backgroundImageView `image` with an `url`, placeholder and custom options.
     *
     * The download is asynchronous and cached.
     *
     * @param url         The url for the image.
     * @param state       The state that uses the specified title. The values are described in UIControlState.
     * @param placeholder The image to be set initially, until the image request finishes.
     * @param options     The options to use when downloading the image. @see SDWebImageOptions for the possible values.
     */
    - (void)sd_setBackgroundImageWithURL:(nullable NSURL *)url
                                forState:(UIControlState)state
                        placeholderImage:(nullable UIImage *)placeholder
                                 options:(SDWebImageOptions)options;
    
    /**
     * Set the backgroundImageView `image` with an `url`.
     *
     * The download is asynchronous and cached.
     *
     * @param url            The url for the image.
     * @param state          The state that uses the specified title. The values are described in UIControlState.
     * @param completedBlock A block called when operation has been completed. This block has no return value
     *                       and takes the requested UIImage as first parameter. In case of error the image parameter
     *                       is nil and the second parameter may contain an NSError. The third parameter is a Boolean
     *                       indicating if the image was retrieved from the local cache or from the network.
     *                       The fourth parameter is the original image url.
     */
    - (void)sd_setBackgroundImageWithURL:(nullable NSURL *)url
                                forState:(UIControlState)state
                               completed:(nullable SDExternalCompletionBlock)completedBlock;
    
    /**
     * Set the backgroundImageView `image` with an `url`, placeholder.
     *
     * The download is asynchronous and cached.
     *
     * @param url            The url for the image.
     * @param state          The state that uses the specified title. The values are described in UIControlState.
     * @param placeholder    The image to be set initially, until the image request finishes.
     * @param completedBlock A block called when operation has been completed. This block has no return value
     *                       and takes the requested UIImage as first parameter. In case of error the image parameter
     *                       is nil and the second parameter may contain an NSError. The third parameter is a Boolean
     *                       indicating if the image was retrieved from the local cache or from the network.
     *                       The fourth parameter is the original image url.
     */
    - (void)sd_setBackgroundImageWithURL:(nullable NSURL *)url
                                forState:(UIControlState)state
                        placeholderImage:(nullable UIImage *)placeholder
                               completed:(nullable SDExternalCompletionBlock)completedBlock;
    
    /**
     * Set the backgroundImageView `image` with an `url`, placeholder and custom options.
     *
     * The download is asynchronous and cached.
     *
     * @param url            The url for the image.
     * @param placeholder    The image to be set initially, until the image request finishes.
     * @param options        The options to use when downloading the image. @see SDWebImageOptions for the possible values.
     * @param completedBlock A block called when operation has been completed. This block has no return value
     *                       and takes the requested UIImage as first parameter. In case of error the image parameter
     *                       is nil and the second parameter may contain an NSError. The third parameter is a Boolean
     *                       indicating if the image was retrieved from the local cache or from the network.
     *                       The fourth parameter is the original image url.
     */
    - (void)sd_setBackgroundImageWithURL:(nullable NSURL *)url
                                forState:(UIControlState)state
                        placeholderImage:(nullable UIImage *)placeholder
                                 options:(SDWebImageOptions)options
                               completed:(nullable SDExternalCompletionBlock)completedBlock;

    4、按钮下载图片的取消方法

    /**
     * Cancel the current image download
        //取消图片下载
     */
    - (void)sd_cancelImageLoadForState:(UIControlState)state;
    
    /**
     * Cancel the current backgroundImage download
        //取消背景图片的下载
     */
    - (void)sd_cancelBackgroundImageLoadForState:(UIControlState)state;

    判断获取图片的格式

    我们根据NSdata获取图片,有的时候需要知道获取图片的格式,分类NSData+ImageContentType就很好的解决了这个问题,我们先看这个方法。

    typedef NS_ENUM(NSInteger, SDImageFormat) {
        SDImageFormatUndefined = -1,
        SDImageFormatJPEG = 0,
        SDImageFormatPNG,
        SDImageFormatGIF,
        SDImageFormatTIFF,
        SDImageFormatWebP
    };
    
    @interface NSData (ImageContentType)
    
    /**
     *  Return image format
     *
     *  @param data the input image data
     *
     *  @return the image format as `SDImageFormat` (enum)
     */
    + (SDImageFormat)sd_imageFormatForImageData:(nullable NSData *)data;
    
    @end

    它的返回值是一个枚举,会返回6中类型,其中一个是未定义类型,下面我们就研究下该方法是如何实现的。

    + (SDImageFormat)sd_imageFormatForImageData:(nullable NSData *)data {
        if (!data) {
            return SDImageFormatUndefined;
        }
        
        uint8_t c;
        [data getBytes:&c length:1];
        switch (c) {
            case 0xFF:
                return SDImageFormatJPEG;
            case 0x89:
                return SDImageFormatPNG;
            case 0x47:
                return SDImageFormatGIF;
            case 0x49:
            case 0x4D:
                return SDImageFormatTIFF;
            case 0x52:
                // R as RIFF for WEBP
                if (data.length < 12) {
                    return SDImageFormatUndefined;
                }
                
                NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(0, 12)] encoding:NSASCIIStringEncoding];
                if ([testString hasPrefix:@"RIFF"] && [testString hasSuffix:@"WEBP"]) {
                    return SDImageFormatWebP;
                }
        }
        return SDImageFormatUndefined;
    }

    缓存图像

    缓存图像这里就包括缓存到disk和memory两种情况。涉及到的类主要就是SDImageCache。下面四中方法都是缓存图像到内存和硬盘,前三种方法都是异步存储,后面一种方法是同步存储。

    #pragma mark - Store Ops
    
    /**
     * Asynchronously store an image into memory and disk cache at the given key.
    //异步存储指定key对应的图片到内存和disk
     *
     * @param image           The image to store
     * @param key             The unique image cache key, usually it's image absolute URL
     * @param completionBlock A block executed after the operation is finished
     */
    - (void)storeImage:(nullable UIImage *)image
                forKey:(nullable NSString *)key
            completion:(nullable SDWebImageNoParamsBlock)completionBlock;
    
    /**
     * Asynchronously store an image into memory and disk cache at the given key.
    //异步存储指定key对应的图片到内存和disk
     *
     * @param image           The image to store
     * @param key             The unique image cache key, usually it's image absolute URL
     * @param toDisk          Store the image to disk cache if YES
     * @param completionBlock A block executed after the operation is finished
     */
    - (void)storeImage:(nullable UIImage *)image
                forKey:(nullable NSString *)key
                toDisk:(BOOL)toDisk
            completion:(nullable SDWebImageNoParamsBlock)completionBlock;
    
    /**
     * Asynchronously store an image into memory and disk cache at the given key.
    //异步存储指定key对应的图片到内存和disk
     *
     * @param image           The image to store
     * @param imageData       The image data as returned by the server, this representation will be used for disk storage
     *                        instead of converting the given image object into a storable/compressed image format in order
     *                        to save quality and CPU
     * @param key             The unique image cache key, usually it's image absolute URL
     * @param toDisk          Store the image to disk cache if YES
     * @param completionBlock A block executed after the operation is finished
     */
    - (void)storeImage:(nullable UIImage *)image
             imageData:(nullable NSData *)imageData
                forKey:(nullable NSString *)key
                toDisk:(BOOL)toDisk
            completion:(nullable SDWebImageNoParamsBlock)completionBlock;
    
    /**
     * Synchronously store image NSData into disk cache at the given key.
     //同步存储指定key对应的NSData对象到disk
     *
     * @warning This method is synchronous, make sure to call it from the ioQueue
     *
     * @param imageData  The image data to store
     * @param key        The unique image cache key, usually it's image absolute URL
     */
    - (void)storeImageDataToDisk:(nullable NSData *)imageData forKey:(nullable NSString *)key;
  • 相关阅读:
    SPOJ
    基础计算几何
    数颜色
    Codeforces 986B
    一些有趣的题
    jQuery
    linux命令学习
    javaScript
    css
    html
  • 原文地址:https://www.cnblogs.com/qiyiyifan/p/10334485.html
Copyright © 2011-2022 走看看