你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> iOS之多線程單例形式、NSOperation、多圖下載、SDWebImage

iOS之多線程單例形式、NSOperation、多圖下載、SDWebImage

編輯:IOS開發綜合

1.單例形式 1.1 概念相關

(1)單例形式

在順序運轉進程,一個類只要一個實例

(2)運用場所

在整個使用順序中,共享一份資源(這份資源只需求創立初始化1次)
1.2 ARC完成單例

(1)步驟

01 在類的外部提供一個static修飾的全局變量
02 提供一個類辦法,方便外界訪問
03 重寫+allocWithZone辦法,保證永遠都只為單例對象分配一次內存空間
04 嚴謹起見,重寫-copyWithZone辦法和-MutableCopyWithZone辦法

(2)相關代碼

//提供一個static修飾的全局變量,強援用著曾經實例化的單例對象實例
static XMGTools *_instance;

//類辦法,前往一個單例對象
+(instancetype)shareTools
{
     //留意:這裡建議運用self,而不是直接運用類名Tools(思索承繼)

    return [[self alloc]init];
}

//保證永遠只分配一次存儲空間
+(instancetype)allocWithZone:(struct _NSZone *)zone
{
    //運用GCD中的一次性代碼
//    static dispatch_once_t onceToken;
//    dispatch_once(&onceToken, ^{
//        _instance = [super allocWithZone:zone];
//    });

    //運用加鎖的方式,保證只分配一次存儲空間
    @synchronized(self) {
        if (_instance == nil) {
            _instance = [super allocWithZone:zone];
        }
    }
    return _instance;
}
/*
1. mutableCopy 創立一個新的可變對象,並初始化為原對象的值,新對象的援用計數為 1;
2. copy 前往一個不可變對象。分兩種狀況:(1)若原對象是不可變對象,那麼前往原對象,並將其援用計數加 1 ;(2)若原對象是可變對象,那麼創立一個新的不可變對象,並初始化為原對象的值,新對象的援用計數為 1。
*/
//讓代碼愈加的嚴謹
-(nonnull id)copyWithZone:(nullable NSZone *)zone
{
//    return [[self class] allocWithZone:zone];
    return _instance;
}

-(nonnull id)mutableCopyWithZone:(nullable NSZone *)zone
{
    return _instance;
}
1.3 MRC完成單例

(1)完成步驟

01 在類的外部提供一個static修飾的全局變量
02 提供一個類辦法,方便外界訪問
03 重寫+allocWithZone辦法,保證永遠都只為單例對象分配一次內存空間
04 嚴謹起見,重寫-copyWithZone辦法和-MutableCopyWithZone辦法
05 重寫release辦法
06 重寫retain辦法
07 建議在retainCount辦法中前往一個最大值

(2)配置MRC環境知識

01 留意ARC不是渣滓回收機制,是編譯器特性
02 配置MRC環境:build setting ->搜索automatic ref->修正為NO

(3)相關代碼

//提供一個static修飾的全局變量,強援用著曾經實例化的單例對象實例
static XMGTools *_instance;

//類辦法,前往一個單例對象
+(instancetype)shareTools
{
     //留意:這裡建議運用self,而不是直接運用類名Tools(思索承繼)

    return [[self alloc]init];
}

//保證永遠只分配一次存儲空間
+(instancetype)allocWithZone:(struct _NSZone *)zone
{
    //運用GCD中的一次性代碼
//    static dispatch_once_t onceToken;
//    dispatch_once(&onceToken, ^{
//        _instance = [super allocWithZone:zone];
//    });

    //運用加鎖的方式,保證只分配一次存儲空間
    @synchronized(self) {
        if (_instance == nil) {
            _instance = [super allocWithZone:zone];
        }
    }
    return _instance;
}

//讓代碼愈加的嚴謹
-(nonnull id)copyWithZone:(nullable NSZone *)zone
{
//    return [[self class] allocWithZone:zone];
    return _instance;
}

-(nonnull id)mutableCopyWithZone:(nullable NSZone *)zone
{
    return _instance;
}

//在MRC環境下,假如用戶retain了一次,那麼直接前往instance變量,不對援用計數器+1
//假如用戶release了一次,那麼什麼都不做,由於單例形式在整個順序運轉進程中都擁有且只要一份,順序加入之後被釋放,所以不需求對援用計數器操作
-(oneway void)release
{
}

-(instancetype)retain
{
    return _instance;
}

//習用法,有經歷的順序員經過打印retainCount這個值可以猜到這是一個單例
-(NSUInteger)retainCount
{
    return MAXFLOAT;
}
1.4 通用版本

(1)有意思的對話

01 問:寫一份單例代碼在ARC和MRC環境下都適用?
答:可以運用條件編譯來判別以後項目環境是ARC還是MRC
02 問:條件編譯的代碼呢,麼麼哒?
//答:條件編譯
#if __has_feature(objc_arc)
//假如是ARC,那麼就執行這裡的代碼1
#else
//假如不是ARC,那麼就執行代理的代碼2
#endif
03 問:在項目外面往往需求完成很多的單例,比方下載、網絡懇求、音樂播放等等,弱弱的問一句單例可以用承繼嗎?
答:單例是不可以用承繼的,假如想一次寫就,四處運用,那麼引薦親運用帶參數的宏定義啦!
04 問:宏定義怎樣弄?
答:這個嘛~~回頭看一眼我的代碼咯,親。

(2)運用帶參數的宏完成通用版單例形式代碼

01 留意條件編譯的代碼不能包括在宏定義外面
02 宏定義的代碼只需求寫一次就好,之後直接拖到項目中用就OK
2.NSOperation 2.1 NSOperation根本運用

(1)相關概念

01 NSOperation是對GCD的包裝
02 兩個中心概念【隊列+操作】

(2)根本運用

01 NSOperation自身是籠統類,只能只要它的子類
02 三個子類辨別是:NSBlockOperation、NSInvocationOperation以及自定義承繼自NSOperation的類
03 NSOperation和NSOperationQueue結合運用完成多線程並發

(3)相關代碼

//  01 NSInvocationOperation
    //1.封裝操作
    /*
     第一個參數:目的對象
     第二個參數:該操作要調用的辦法,最多承受一個參數
     第三個參數:調用辦法傳遞的參數,假如辦法不承受參數,那麼該值傳nil
     */
    NSInvocationOperation *operation = [[NSInvocationOperation alloc]
                                        initWithtarget:self selector:@selector(run) object:nil];

    //2.啟動操作
    [operation start];
-------------------------------------------------
    //  02 NSBlockOperation
    //1.封裝操作
    /*
     NSBlockOperation提供了一個類辦法,在該類辦法中封裝操作
     */
    NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
        //在主線程中執行
        NSLog(@"---download1--%@",[NSThread currentThread]);
    }];

    //2.追加操作,追加的操作在子線程中執行
    [operation addExecutionBlock:^{
        NSLog(@"---download2--%@",[NSThread currentThread]);
    }];

    [operation addExecutionBlock:^{
         NSLog(@"---download3--%@",[NSThread currentThread]);
    }];

    //3.啟動執行操作
    [operation start];

----------------------------------------------
// 03 自定義NSOperation
    //如何封裝操作?
    //自定義的NSOperation,經過重寫外部的main辦法完成封裝操作
    -(void)main
    {
        NSLog(@"--main--%@",[NSThread currentThread]);
    }

    //如何運用?
    //1.實例化一個自定義操作對象
    XMGOperation *op = [[XMGOperation alloc]init];

    //2.執行操作
    [op start];
2.2 NSOperationQueue根本運用

(1)NSOperation中的兩種隊列

01 客隊列 經過mainQueue取得,但凡放到客隊列中的義務都將在主線程執行
02 非客隊列 直接alloc init出來的隊列。非客隊列同時具有了並發和串行的功用,經過設置最大並發數屬性來控制義務是並發執行還是串行執行

(2)相關代碼

//自定義NSOperation
-(void)customOperation
{
    //1.創立隊列
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];

    //2.封裝操作
    //益處:1.信息蔭蔽
    //2.代碼復用

    XMGOperation *op1 = [[XMGOperation alloc]init];
    XMGOperation *op2 = [[XMGOperation alloc]init];

    //3.添加操作到隊列中
    [queue addOperation:op1];
    [queue addOperation:op2];
}

//NSBlockOperation
- (void)block
{
    //1.創立隊列
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];

    //2.封裝操作
    NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"1----%@",[NSThread currentThread]);
    }];

    NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"2----%@",[NSThread currentThread]);

    }];

    [op2 addExecutionBlock:^{
        NSLog(@"3----%@",[NSThread currentThread]);
    }];

    [op2 addExecutionBlock:^{
        NSLog(@"4----%@",[NSThread currentThread]);
    }];

    //3.添加操作到隊列中
    [queue addOperation:op1];
    [queue addOperation:op2];

    //補充:簡便辦法
    [queue addOperationWithBlock:^{
        NSLog(@"5----%@",[NSThread currentThread]);
    }];

}

//NSInvocationOperation
- (void)invocation
{
    /*
     GCD中的隊列:
     串行隊列:自己創立的,客隊列
     並發隊列:自己創立的,全局並發隊列

     NSOperationQueue
     客隊列:[NSOperationQueue mainqueue];凡事放在客隊列中的操作都在主線程中執行
     非客隊列:[[NSOperationQueue alloc]init],並發和串行,默許是並發執行的
     */

    //1.創立隊列
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];

    //2.封裝操作
    NSInvocationOperation *op1 = [[NSInvocationOperation alloc]initWithtarget:self selector:@selector(download1) object:nil];

    NSInvocationOperation *op2 = [[NSInvocationOperation alloc]initWithtarget:self selector:@selector(download2) object:nil];


    NSInvocationOperation *op3 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(download3) object:nil];


    //3.把封裝好的操作添加到隊列中
    [queue addOperation:op1];//[op1 start]
    [queue addOperation:op2];
    [queue addOperation:op3];
}
2.3 NSOperation其它用法

(1)設置最大並發數【控制義務並發和串行】

//1.創立隊列
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];

    //2.設置最大並發數
    //留意點:該屬性需求在義務添加到隊列中之行進行設置
    //該屬性控制隊列是串行執行還是並發執行
    //假如最大並發數等於1,那麼該隊列是串行的,假如大於1那麼是並行的
    //零碎的最大並發數有個默許的值,為-1,假如該屬性設置為0,那麼不會執行任何義務
    queue.maxConcurrentOperationCount = 2;

(2)暫停和恢復以及取消

    //設置暫停和恢復
    //suspended設置為YES表示暫停,suspended設置為NO表示恢復
    //暫停表示不持續執行隊列中的下一個義務,暫停操作是可以恢復的
    if (self.queue.isSuspended) {
        self.queue.suspended = NO;
    }else
    {
        self.queue.suspended = YES;
    }

    //取消隊列外面的一切操作
    //取消之後,以後正在執行的操作的下一個操作將不再執行,而且永遠都不在執行,好像前面的一切義務都從隊列外面移除了一樣
    //取消操作是不可以恢復的
    [self.queue cancelAllOperations];

---------自定義NSOperation取消操作--------------------------
-(void)main
{
    //耗時操作1
    for (int i = 0; i<1000; i++) {
        NSLog(@"義務1-%d--%@",i,[NSThread currentThread]);
    }
    NSLog(@"+++++++++++++++++++++++++++++++++");

    //蘋果官方建議,每當執行完一次耗時操作之後,就檢查一下以後隊列能否為取消形態,假如是,那麼就直接加入
    //益處是可以進步順序的功能
    if (self.isCancelled) {
        return;
    }

    //耗時操作2
    for (int i = 0; i<1000; i++) {
        NSLog(@"義務1-%d--%@",i,[NSThread currentThread]);
    }

    NSLog(@"+++++++++++++++++++++++++++++++++");
}
2.4 NSOperation完成線程間通訊

(1)開子線程下載圖片

 //1.創立隊列
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];

    //2.運用簡便辦法封裝操作並添加到隊列中
    [queue addOperationWithBlock:^{

        //3.在該block中下載圖片
        NSURL *url = [NSURL URLWithString:@"http://news.51sheyuan.com/uploads/allimg/111001/133442IB-2.jpg"];
        NSData *data = [NSData dataWithContentsOfURL:url];
        UIImage *image = [UIImage imageWithData:data];
        NSLog(@"下載圖片操作--%@",[NSThread currentThread]);

        //4.回到主線程刷新UI
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            self.imageView.image = image;
            NSLog(@"刷新UI操作---%@",[NSThread currentThread]);
        }];
    }];

(2)下載多張圖片分解綜合案例(設置操作依賴)

//02 綜合案例
- (void)download2
{
    NSLog(@"----");
    //1.創立隊列
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];

    //2.封裝操作下載圖片1
    NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{

        NSURL *url = [NSURL URLWithString:@"http://h.hiphotos.baidu.com/zhidao/pic/item/6a63f6246b600c3320b14bb3184c510fd8f9a185.jpg"];
        NSData *data = [NSData dataWithContentsOfURL:url];

        //拿到圖片數據
        self.image1 = [UIImage imageWithData:data];
    }];


    //3.封裝操作下載圖片2
    NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
        NSURL *url = [NSURL URLWithString:@"http://pic.58pic.com/58pic/13/87/82/27Q58PICYje_1024.jpg"];
        NSData *data = [NSData dataWithContentsOfURL:url];

        //拿到圖片數據
        self.image2 = [UIImage imageWithData:data];
    }];

    //4.分解圖片
    NSBlockOperation *combine = [NSBlockOperation blockOperationWithBlock:^{

        //4.1 開啟圖形上下文
        UIGraphicsBeginImageContext(CGSizeMake(200, 200));

        //4.2 畫image1
        [self.image1 draWinRect:CGRectMake(0, 0, 200, 100)];

        //4.3 畫image2
        [self.image2 draWinRect:CGRectMake(0, 100, 200, 100)];

        //4.4 依據圖形上下文拿到圖片數據
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
//        NSLog(@"%@",image);

        //4.5 封閉圖形上下文
        UIGraphicsEndImageContext();

        //7.回到主線程刷新UI
        [[NSOperationQueue mainQueue]addOperationWithBlock:^{
            self.imageView.image = image;
            NSLog(@"刷新UI---%@",[NSThread currentThread]);
        }];

    }];

    //5.設置操作依賴
    [combine addDependency:op1];
    [combine addDependency:op2];

    //6.添加操作到隊列中執行
    [queue addOperation:op1];
    [queue addOperation:op2];
    [queue addOperation:combine];
    }
3.多圖下載綜合示例順序

(1)觸及知識點

     01 字典轉模型
     02 存儲數據到沙盒,從沙盒中加載數據
     03 占位圖片的設置(cell的刷新問題)
     04 如何停止內存緩存(運用NSDictionary)
     05 在順序開發進程中的一些容錯處置
     06 如何刷新tableView的指定行(處理數據紊亂問題)
     07 NSOperation以及線程間通訊相關知識
4.第三方框架

(1)SDWebImage根本運用

    01 設置imageView的圖片
    [cell.imageView sd_setImageWithURL:[NSURL URLWithString:app.icon] placeholderImage:[UIImage imageNamed:@"placehoder"]];

    02 設置圖片並計算下載進度
       //下載並設置圖片
    /*
     第一個參數:要下載圖片的url地址
     第二個參數:設置該imageView的占位圖片
     第三個參數:傳一個枚舉值,通知順序你下載圖片的戰略是什麼
     第一個block塊:獲取以後圖片數據的下載進度
         receivedSize:曾經下載完成的數據大小
         expectedSize:該文件的數據總大小
     第二個block塊:當圖片下載完成之後執行該block中的代碼
         image:下載失掉的圖片數據
         error:下載呈現的錯誤信息
         SDImageCacheType:圖片的緩存戰略(不緩存,內存緩存,沙盒緩存)
         imageURL:下載的圖片的url地址
     */
    [cell.imageView sd_setImageWithURL:[NSURL URLWithString:app.icon] placeholderImage:[UIImage imageNamed:@"placehoder"] options:SDWebImageRetryFailed progress:^(NSInteger receivedSize, NSInteger expectedSize) {

        //計算以後圖片的下載進度
        NSLog(@"%.2f",1.0 *receivedSize / expectedSize);

    } completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {

    }];

    03 零碎級內存正告如何處置(面試)
    //取消以後正在停止的一切下載操作
    [[SDWebImageManager sharedManager] cancelAll];

    //肅清緩存數據(面試)
    //cleanDisk:刪除過時的文件數據,計算以後未過時的曾經下載的文件數據的大小,假如發現該數據大小大於我們設置的最大緩存數據大小,那麼順序外部會依照按文件數據緩存的時間從遠到近刪除,知道小於最大緩存數據為止。

    //clearMemory:直接刪除文件,重新創立新的文件夾
    //[[SDWebImageManager sharedManager].imageCache cleanDisk];
    [[SDWebImageManager sharedManager].imageCache clearMemory];

    04 SDWebImage默許的緩存時間是1周
    05 如何播放gif圖片
    /*
    5-1 把用戶傳入的gif圖片->NSData
    5-2 依據該Data創立一個圖片數據源(NSData->CFImageSourceRef)
    5-3 計算該數據源中一共有多少幀,把每一幀數據取出來放到圖片數組中
    5-4 依據失掉的數組+計算的動畫時間-》可動畫的image
    [UIImage animatedImageWithImages:images duration:duration];
    */

    06 如何判別以後圖片類型
    + (NSString *)sd_contentTypeForImageData:(NSData *)data;

(2)SDWebImage外部構造

IOS之多線程單例模式、NSOperation、多圖下載、SDWebImage

【iOS之多線程單例形式、NSOperation、多圖下載、SDWebImage】的相關資料介紹到這裡,希望對您有所幫助! 提示:不會對讀者因本文所帶來的任何損失負責。如果您支持就請把本站添加至收藏夾哦!

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved