Objective-cマルチスレッド操作カスタムNSOperationシミュレーションダウンロード

11889 ワード

前に書いて人を降ろして...コンテンツが再びロックされないように...全てがここにある
前に書く
マルチスレッドを使用して画像をダウンロードし、メモリキャッシュとディスクキャッシュを使用します.ここではNSOperationとその派生クラスを理解するためにアプリに適用するには、成熟したサードパーティライブラリをダウンロードしてください.
効果
効果
複数のピクチャをダウンロードするときにスレッドの同時数を制御できます
ぶんせき
  • カスタムNSOperation実行ダウンロード操作
  • は1つのキュー操作をカプセル化し、N個のスレッドを作成し、キュー制御は
  • を併発する.
  • スレッドtagにより対応ピクチャ
  • を検索する
  • キューtagにより対応するキュー
  • を検索する.
  • キャッシュメモリとディスクキャッシュ
  • を設定する.
  • ダウンロード完了delegateまたはblockによるコールバック通知
  • コード#コード#
  • 汎用コンテンツスレッド完了時のコールバック、ピクチャロード時のコールバック
  • #ifndef Uinty_h
    #define Uinty_h
    #import 
    
    typedef void(^DownloadImageDataBlock)(NSData *data,int tag);
    typedef void(^DownloadImageBlock)(UIImage *image,int tag,int queueTag);
    
    static int const  kImageViewTag = 1990;
    //      
    @protocol DownloadOperationDelegate 
    //        
    - (void)downloadOperationWithData:(NSData*)data withTag:(int)tag;
    
    @end
    
    //      
    @protocol DownloadImageDelegate 
    //    
    - (void)downloadImageFinishedWith:(UIImage*)image andTag:(int)tag withQueueTag:(int)queueTag;
    @end
    #endif /* Uinty_h */
    
  • カスタムNSOperationダウンロードデータ
  • #import 
    #import "Uinty.h"
    @interface DownloadOperation : NSOperation
    
    //block
    @property (nonatomic,copy)DownloadImageDataBlock imageDataBlock;
    //  
    @property (nonatomic,assign)int tag;
    
    //  
    @property (nonatomic,strong)id delegate;
    
    //   
    - (instancetype)initWithUrlStr:(NSString*)urlStr;
    
    + (instancetype)downloadOperationWithUrlStr:(NSString*)urlStr;
    @end
    
    
    #import "DownloadOperation.h"
    @interface DownloadOperation()
    @property(nonatomic,copy)NSString *urlStr;
    
    @end
    
    @implementation DownloadOperation
    
    - (instancetype)initWithUrlStr:(NSString*)urlStr {
        self = [super init];
        if (self) {
            self.urlStr = urlStr;
        }
        return self;
    }
    
    + (instancetype)downloadOperationWithUrlStr:(NSString*)urlStr {
        return [[DownloadOperation alloc] initWithUrlStr:urlStr];
    }
    
    -(void)main {
    
        NSURL *url = [NSURL URLWithString:self.urlStr];
        NSData *data = [NSData dataWithContentsOfURL:url];
        //    
        sleep(1);
        //     
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            //block  
            if (self.imageDataBlock) {
                self.imageDataBlock(data,self.tag);
            }
            //    
            if ([self.delegate respondsToSelector:@selector(downloadOperationWithData:withTag:)]) {
                [self.delegate downloadOperationWithData:data withTag:self.tag];
            }
        }];
        }
    @end
    
  • ロードピクチャ:キャッシュロードとスレッドキューロード
  • #import 
    #import "DownloadOperation.h"
    @interface DownloadImage : NSObject
    //    
    @property (nonatomic,copy)DownloadImageBlock downloadFinishedBlock;
    //       
    @property (nonatomic,copy)NSString *urlStr;
    //       
    @property (nonatomic,strong)NSArray *urlArray;
    //         
    @property (nonatomic,assign)int  maxOperationCount;
    //  
    @property (nonatomic,strong)id delegate;
    //  
    @property (nonatomic,assign)int tag;
    //            :M
    @property (nonatomic,assign)NSUInteger diskCapacity;
    @property (nonatomic,assign)NSUInteger MemoryCapacity;
    
    //    url  
    - (instancetype)initWithUrlStrArray:(NSArray*)urlArray withStartTag:(int)startTag ;
    //    url
    - (instancetype)initWithUrlStr:(NSString*)urlStr ;
    //   
    + (instancetype)downloadImageWithUrlStrArray:(NSArray*)urlArray withStartTag:(int)startTag ;
    + (instancetype)downloadImageWithUrlStr:(NSString*)urlStr ;
    
    //    
    - (void)starDownloadImage;
    @end
    
    //
    //  DownloadImage.m
    //  DownloadImageDemo
    //
    //  Created by gongwenkai on 2017/1/3.
    //  Copyright © 2017  gongwenkai. All rights reserved.
    //
    
    #import "DownloadImage.h"
    #import "DownloadOperation.h"
    
    
    @interface DownloadImage()
    @property (nonatomic,strong)NSOperationQueue *queue;
    @property (nonatomic,strong)NSCache *imageCache;
    @property (nonatomic,copy)NSString *cachePath;
    @property (nonatomic,assign)int imageStartTag;
    
    @end
    
    @implementation DownloadImage
    
    #pragma mark -    
    - (NSString *)cachePath {
        if (!_cachePath) {
            _cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
        }
        return _cachePath;
    }
    
    - (NSCache *)imageCache {
        if (!_imageCache) {
            _imageCache = [[NSCache alloc] init];
            _imageCache.countLimit = 100;
            
        }
        return _imageCache;
    }
    
    - (NSOperationQueue *)queue {
        if (!_queue) {
            _queue = [[NSOperationQueue alloc] init];
        }
        return _queue;
    }
    
    - (NSUInteger)MemoryCapacity {
        if (!_MemoryCapacity) {
            _MemoryCapacity = 1;
        }
        return _MemoryCapacity;
    }
    
    - (NSUInteger)diskCapacity {
        if (!_diskCapacity) {
            _diskCapacity = 10;
        }
        return _diskCapacity;
    }
    
    - (int)maxOperationCount {
        if (!_maxOperationCount) {
            _maxOperationCount = 2;
        }
        return _maxOperationCount;
    }
    
    #pragma mark -    
    + (instancetype)downloadImageWithUrlStrArray:(NSArray*)urlArray withStartTag:(int)startTag {
        return [[DownloadImage alloc] initWithUrlStrArray:urlArray withStartTag:startTag];
    }
    
    + (instancetype)downloadImageWithUrlStr:(NSString*)urlStr {
        return [[DownloadImage alloc] initWithUrlStr:urlStr];
    }
    
    - (instancetype)initWithUrlStrArray:(NSArray*)urlArray withStartTag:(int)startTag{
        self = [super init];
        if (self) {
            self.urlArray = urlArray;
            self.imageStartTag = startTag;
        }
        return self;
    }
    
    - (instancetype)initWithUrlStr:(NSString*)urlStr {
        self = [super init];
        if (self) {
            self.urlStr = urlStr;
        }
        return self;
    }
    
    //    set     url    
    - (void)setUrlStr:(NSString *)urlStr {
        _urlStr = urlStr;
        _urlArray = [NSArray arrayWithObject:urlStr];
    }
    
    
    #pragma mark -     
    - (void)starDownloadImage {
        
        //             
        NSURLCache *URLCache = [[NSURLCache alloc] initWithMemoryCapacity:self.MemoryCapacity * 1024 * 1024 diskCapacity:self.diskCapacity * 1024 * 1024 diskPath:nil];
        [NSURLCache setSharedURLCache:URLCache];
    
        //    
        for (int i = 0; i < self.urlArray.count; i++) {
            int imageTag = self.imageStartTag + i;
            NSString *urlStr = self.urlArray[i];
            //          
            UIImage *memoryImage = [self.imageCache objectForKey:urlStr];
            if (memoryImage) {
                //block    
                if (self.downloadFinishedBlock) {
                    self.downloadFinishedBlock(memoryImage,imageTag,self.tag);
                }
                //      
                if ([self.delegate respondsToSelector:@selector(downloadImageFinishedWith:andTag:withQueueTag:)]) {
                    [self.delegate downloadImageFinishedWith:memoryImage andTag:imageTag withQueueTag:self.tag];
                }
                continue;
            }
            //          
            NSString *imagePath=[urlStr lastPathComponent];
            NSString *imageCachePath = [self.cachePath stringByAppendingPathComponent:imagePath];
            NSData *data = [NSData dataWithContentsOfFile:imageCachePath];
            if (data) {
                UIImage *diskImage = [UIImage imageWithData:data];
                //block    
                if (self.downloadFinishedBlock) {
                    self.downloadFinishedBlock(diskImage,imageTag,self.tag);
                }
                //      
                if ([self.delegate respondsToSelector:@selector(downloadImageFinishedWith:andTag:withQueueTag:)]) {
                    [self.delegate downloadImageFinishedWith:diskImage andTag:imageTag withQueueTag:self.tag];
                }
                continue;
            }
            
            
            //        
            self.queue.maxConcurrentOperationCount = self.maxOperationCount;
            DownloadOperation *op = [DownloadOperation downloadOperationWithUrlStr:urlStr];
            
            op.tag = i + kImageViewTag;
            if (self.urlArray.count < self.maxOperationCount) {
                [op start];
            }else {
                [self.queue addOperation:op];
            }
        
            //      
            op.imageDataBlock = ^(NSData *data,int tag){
                UIImage *image = [UIImage imageWithData:data];
                
                //      
                [self.imageCache setObject:image forKey:urlStr];
                //      
                [data writeToFile:imageCachePath atomically:YES];
                
                //block  
                if (self.downloadFinishedBlock) {
                    NSLog(@"tage ======%d",tag);
                    self.downloadFinishedBlock(image,tag,self.tag);
                }
                //    
                if ([self.delegate respondsToSelector:@selector(downloadImageFinishedWith:andTag:withQueueTag:)]) {
                    [self.delegate downloadImageFinishedWith:image andTag:tag withQueueTag:self.tag];
                }
                
            };
    
        }
        
    }
    
    @end
    
    
  • 外部呼び出しおよびテスト
  • - (void)viewDidLoad {
        [super viewDidLoad];
    
        for (int i = 0; i < 6; i++) {
            UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(0, i*105, 100, 100)];
            imgView.tag = i + kImageViewTag;
            imgView.backgroundColor = [UIColor redColor];
            [self.view addSubview:imgView];
        }
        
        UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(120, 100, 100, 100)];
        imgView.backgroundColor = [UIColor redColor];
        imgView.tag = 1234;
        [self.view addSubview:imgView];
        NSLog(@"%@",NSHomeDirectory());
    }
    
    
    - (IBAction)clickLoadImages:(id)sender {
        //      
        DownloadImage *download = [DownloadImage downloadImageWithUrlStrArray:@[@"http://img.hb.aicdn.com/6e004cb3c5f58f016a57b90f8bbb93d7075453f2efd0-anTckt_fw658",@"http://img.hb.aicdn.com/fb18b522caf2821adb7af96f8656787f8d9bdad31bdec-6f6h4X_fw658",@"http://img.hb.aicdn.com/22e4dfd8d135de7ae0d451e351c00bddf732919920840-BMRw4Z_fw658",@"http://img.hb.aicdn.com/536c96af48b38faca5bcad20ba0ea6aba8929b711e5b4-lvdBlI_fw658",@"http://img.hb.aicdn.com/055e5458bd340a52ca0067f5d7c22b6c3b18d119292ae-QLEsYp_fw658",@"http://img.hb.aicdn.com/b50481ab8a2b4e3587068df0552ebad08409f0b3ca23-8gBQ9x_fw658"] withStartTag:kImageViewTag];
        //     
        download.maxOperationCount = 3;
        download.tag = 0;
        download.delegate = self;
        /*   block      
         download.downloadFinishedBlock = ^(UIImage *image,int tag,int queueTag) {
         UIImageView *img = [self.view viewWithTag:tag];
         img.image = image;
         NSLog(@"jicia====%d",tag);
         };
         */
        //    
        [download starDownloadImage];
    }
    
    - (IBAction)clickLoadSingalImage:(id)sender {
        //    
        DownloadImage *down = [DownloadImage downloadImageWithUrlStr:@"http://img.hb.aicdn.com/b50481ab8a2b4e3587068df0552ebad08409f0b3ca23-8gBQ9x_fw658"];
        down.tag = 1;
        down.delegate = self;
        
        /*   block      
         down.downloadFinishedBlock = ^(UIImage *image,int tag,int queueTag) {
         UIImageView *imgV = [self.view viewWithTag:1234];
         imgV.image = image;
         };
         */
        [down starDownloadImage];
        
    }
    - (IBAction)cleanAll:(id)sender {
        
        for (int i = 0; i < 6; i++) {
            UIImageView *imgView = [self.view viewWithTag:i + kImageViewTag];
            imgView.image = nil;
        }
        UIImageView *imgView = [self.view viewWithTag:1234];
        imgView.image = nil;
        
    }
    
    //        
    - (void)downloadImageFinishedWith:(UIImage*)image andTag:(int)tag withQueueTag:(int)queueTag{
        if (queueTag == 0) {
            UIImageView *img = [self.view viewWithTag:tag];
            img.image = image;
        } else if (queueTag == 1) {
            UIImageView *imgV = [self.view viewWithTag:1234];
            imgV.image = image;
        }
    
    }
    

    DEMOアドレス
    https://github.com/gongxiaokai/DownloadImageDemo