IOS 异步加载图片

 1 #import <Foundation/Foundation.h>
 2 #import "StringUtils.h"
 3 
 4 @interface ImageManager : NSObject
 5 {
 6     NSMutableDictionary *_imageDict;
 7     NSMutableArray *_imageArr;
 8 }
 9 
10 @property(nonatomic, strong) NSString *httpUrl;
11 @property(nonatomic, strong) NSMutableDictionary *imageDict;
12 
13 @property(nonatomic, assign) dispatch_queue_t networkQueue;
14 
15 + (ImageManager *) sharedInstance;
16 
17 
18 - (void)asyncImage:(NSString *)imageName imageView:(UIImageView *)imageView;
19 //插队
20 - (void)asyncImageInsert:(NSString *)imageName imageView:(UIImageView *)imageView insert:(BOOL)insert;
21 //不要在下载之前的数据
22 - (void)asyncImageCleanOld:(NSString *)imageName imageView:(UIImageView *)imageView cleanOld:(BOOL)cleanOld;
23 
24 @end

实现文件

//
//  ImageManager.m
//  myb-ios
//
//  Created by warrior gao on 13-6-5.
//  Copyright (c) 2013年 51myb. All rights reserved.
//

#import "ImageManager.h"

@interface ImageManager()

@end

@implementation ImageManager

//缓存图片的最大数量
static int counter = 0;

@synthesize imageDict = _imageDict;

//Singleton 
+ (ImageManager *)sharedInstance
{
    static id instance;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = self.new;
    });
    return instance;
}

- (id)init
{
    if((self = [super init]))
    {
        self.networkQueue = dispatch_queue_create("com.warrior.network.image", nil);
        _imageDict = [[NSMutableDictionary alloc] init];
        _imageArr = [[NSMutableArray alloc] init];
    }
    return self;
}

- (NSString *) fileFullPath:(NSString *)fileName
{
    NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    
    NSString *fileFullPath = [NSString stringWithFormat:@"%@/%@",cachePath,fileName];
    
    return fileFullPath;
}

//不要在下载之前的数据
- (void)asyncImageCleanOld:(NSString *)imageName imageView:(UIImageView *)imageView cleanOld:(BOOL)cleanOld
{
    if(cleanOld)
    {
        [_imageArr removeAllObjects];
    }
    
    [self asyncImage:imageName imageView:imageView];
}

//插队,优先
- (void)asyncImageInsert:(NSString *)imageName imageView:(UIImageView *)imageView insert:(BOOL)insert
{
    if([StringUtils isEmpty:imageName]){
        return;
    }
    
    NSData *data = [NSData dataWithContentsOfFile:[self fileFullPath:[imageName stringByReplacingOccurrencesOfString:@"/" withString:@"-"]]];
    if(data == nil){
        [_imageDict setValue:imageView forKey:imageName];
        if(insert)
        {
            [_imageArr insertObject:imageName atIndex:0];
        }
        else
        {
            [_imageArr addObject:imageName];
        }
        
        [self cacheImage];
    } else {
        [imageView setImage:[UIImage imageWithData:data]];
    }
}

//正常,附加到后面
- (void)asyncImage:(NSString *)imageName imageView:(UIImageView *)imageView
{
    [self asyncImageInsert:imageName imageView:imageView insert:NO];
}

//异步缓存图片到本地,最多有两个线程
-(void)cacheImage
{
    for (; counter < 2 && _imageArr.count > 0; counter++)
    {
        NSString *imageName = nil;
        @synchronized(self){
            imageName = [[_imageArr objectAtIndex:0] copy];
            [_imageArr removeObjectAtIndex:0];
        }
        
        if(imageName == nil) continue;
        
        dispatch_async(self.networkQueue, ^{
            
            NSLog(@"Starting: %@", imageName);
            UIImage *avatarImage = nil;
            NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%@%@",self.httpUrl, imageName]];
            NSData *responseData = [NSData dataWithContentsOfURL:url];
            if(responseData.length > 0)
            {
                [responseData writeToFile:[self fileFullPath:[imageName stringByReplacingOccurrencesOfString:@"/" withString:@"-"]] atomically:NO];
                avatarImage = [UIImage imageWithData:responseData];
                NSLog(@"Finishing: %@", imageName);
                
                if (avatarImage) {
                    dispatch_async(dispatch_get_main_queue(), ^{
                        UIImageView *imageView = [_imageDict objectForKey:imageName];
                        if(imageView != nil && avatarImage != nil){
                            [imageView setImage:avatarImage];
                        }
                        
                        [_imageDict removeObjectForKey:imageName];
                        [imageName release];
                    });
                }
            }
            counter--;
            [self cacheImage];
        });
        
    }
}

@end

问题,因为对imageView和图片管理器耦合在一起,非常难用。等一下我将放出重构后的代码。

原文地址:https://www.cnblogs.com/warrior/p/3329552.html