iOS 多線程中NSOperation的使用

1. NSOperation基本使用

(1)相關(guān)概念

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

(2)基本使用

01 NSOperation本身是抽象類镐侯,只能只有它的子類
02 三個子類分別是:NSBlockOperation先誉、NSInvocationOperation以及自定義繼承自NSOperation的類
03 NSOperation和NSOperationQueue結(jié)合使用實現(xiàn)多線程并發(fā)

(3)相關(guān)代碼

//  01 NSInvocationOperation
    //1.封裝操作
    /*
     第一個參數(shù):目標對象
     第二個參數(shù):該操作要調(diào)用的方法,最多接受一個參數(shù)
     第三個參數(shù):調(diào)用方法傳遞的參數(shù)贝润,如果方法不接受參數(shù),那么該值傳nil
     */
    NSInvocationOperation *operation = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(run) object:nil];

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

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

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

    //3.啟動執(zhí)行操作
    [operation start];

----------------------------------------------
// 03 自定義NSOperation
    //如何封裝操作?
    //自定義的NSOperation,通過重寫內(nèi)部的main方法實現(xiàn)封裝操作
    -(void)main
    {
        NSLog(@"--main--%@",[NSThread currentThread]);
    }

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

    //2.執(zhí)行操作
    [op start];

2. NSOperationQueue基本使用

(1)NSOperation中的兩種隊列

01 主隊列 通過mainQueue獲得,凡是放到主隊列中的任務(wù)都將在主線程執(zhí)行
02 非主隊列 直接alloc init出來的隊列高职。非主隊列同時具備了并發(fā)和串行的功能钩乍,通過設(shè)置最大并發(fā)數(shù)屬性來控制任務(wù)是并發(fā)執(zhí)行還是串行執(zhí)行

(2)相關(guān)代碼

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

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

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

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

//NSBlockOperation
- (void)block
{
    //1.創(chuàng)建隊列
    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中的隊列:
     串行隊列:自己創(chuàng)建的,主隊列
     并發(fā)隊列:自己創(chuàng)建的怔锌,全局并發(fā)隊列

     NSOperationQueue
     主隊列:[NSOperationQueue mainqueue];凡是放在主隊列中的操作都在主線程中執(zhí)行
     非主隊列:[[NSOperationQueue alloc]init]寥粹,并發(fā)和串行变过,默認是并發(fā)執(zhí)行的
     */

    //1.創(chuàng)建隊列
    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];
}

3. NSOperation其它用法

(1)設(shè)置最大并發(fā)數(shù)【控制任務(wù)并發(fā)和串行】

//1.創(chuàng)建隊列
    NSOperationQueue *queue = [[NSOperationQueue alloc]init];

    //2.設(shè)置最大并發(fā)數(shù)
    //注意點:該屬性需要在任務(wù)添加到隊列中之前進行設(shè)置
    //該屬性控制隊列是串行執(zhí)行還是并發(fā)執(zhí)行
    //如果最大并發(fā)數(shù)等于1,那么該隊列是串行的涝涤,如果大于1那么是并行的
    //系統(tǒng)的最大并發(fā)數(shù)有個默認的值媚狰,為-1,如果該屬性設(shè)置為0阔拳,那么不會執(zhí)行任何任務(wù)
    queue.maxConcurrentOperationCount = 2;

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

    //設(shè)置暫停和恢復
    //suspended設(shè)置為YES表示暫停崭孤,suspended設(shè)置為NO表示恢復
    //暫停表示不繼續(xù)執(zhí)行隊列中的下一個任務(wù),暫停操作是可以恢復的
    if (self.queue.isSuspended) {
        self.queue.suspended = NO;
    }else
    {
        self.queue.suspended = YES;
    }

    //取消隊列里面的所有操作
    //取消之后糊肠,當前正在執(zhí)行的操作的下一個操作將不再執(zhí)行辨宠,而且永遠都不在執(zhí)行,就像后面的所有任務(wù)都從隊列里面移除了一樣
    //取消操作是不可以恢復的
    [self.queue cancelAllOperations];

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

    //蘋果官方建議罪针,每當執(zhí)行完一次耗時操作之后彭羹,就查看一下當前隊列是否為取消狀態(tài)黄伊,如果是泪酱,那么就直接退出
    //好處是可以提高程序的性能
    if (self.isCancelled) {
        return;
    }

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

    NSLog(@"+++++++++++++++++++++++++++++++++");
}

4. NSOperation實現(xiàn)線程間通信

(1)開子線程下載圖片

 //1.創(chuàng)建隊列
    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)下載多張圖片合成綜合案例(設(shè)置操作依賴)

//02 綜合案例
- (void)download2
{
    NSLog(@"----");
    //1.創(chuàng)建隊列
    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];

        //拿到圖片數(shù)據(jù)
        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];

        //拿到圖片數(shù)據(jù)
        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 根據(jù)圖形上下文拿到圖片數(shù)據(jù)
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
//        NSLog(@"%@",image);

        //4.5 關(guān)閉圖形上下文
        UIGraphicsEndImageContext();

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

    }];

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

    //6.添加操作到隊列中執(zhí)行
    [queue addOperation:op1];
    [queue addOperation:op2];
    [queue addOperation:combine];
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市还最,隨后出現(xiàn)的幾起案子墓阀,更是在濱河造成了極大的恐慌,老刑警劉巖拓轻,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件斯撮,死亡現(xiàn)場離奇詭異,居然都是意外死亡扶叉,警方通過查閱死者的電腦和手機勿锅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來枣氧,“玉大人溢十,你說我怎么就攤上這事〈锿蹋” “怎么了张弛?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長酪劫。 經(jīng)常有香客問我吞鸭,道長,這世上最難降的妖魔是什么覆糟? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任刻剥,我火速辦了婚禮,結(jié)果婚禮上滩字,老公的妹妹穿的比我還像新娘造虏。我一直安慰自己盯滚,他們只是感情好,可當我...
    茶點故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布酗电。 她就那樣靜靜地躺著魄藕,像睡著了一般。 火紅的嫁衣襯著肌膚如雪撵术。 梳的紋絲不亂的頭發(fā)上背率,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天,我揣著相機與錄音嫩与,去河邊找鬼寝姿。 笑死,一個胖子當著我的面吹牛划滋,可吹牛的內(nèi)容都是我干的饵筑。 我是一名探鬼主播,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼处坪,長吁一口氣:“原來是場噩夢啊……” “哼根资!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起同窘,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤玄帕,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后想邦,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體裤纹,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡搜变,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年场勤,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片着逐。...
    茶點故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡呕童,死狀恐怖漆际,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情拉庵,我是刑警寧澤灿椅,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站钞支,受9級特大地震影響茫蛹,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜烁挟,卻給世界環(huán)境...
    茶點故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一婴洼、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧撼嗓,春花似錦柬采、人聲如沸欢唾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽礁遣。三九已至,卻和暖如春肩刃,著一層夾襖步出監(jiān)牢的瞬間祟霍,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工盈包, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留沸呐,地道東北人。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓呢燥,卻偏偏與公主長得像崭添,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子叛氨,可洞房花燭夜當晚...
    茶點故事閱讀 42,802評論 2 345

推薦閱讀更多精彩內(nèi)容