第十四章蟆湖、代碼塊和并發(fā)性

  • 代碼塊:一個可以增強(qiáng)函數(shù)功能的Objective-C特性
  • 并發(fā)性:如何讓現(xiàn)代設(shè)備同時執(zhí)行多個任務(wù)

1.代碼塊

  • 代碼塊對象(簡稱代碼塊):是對C語言中函數(shù)的擴(kuò)展玻粪。除了函數(shù)中的代碼,代碼塊還包含變量綁定结窘。代碼塊有時也被稱為閉包隧枫。
  • 代碼塊包含兩種類型的綁定:自動型與托管型谓苟。自動綁定使用的是棧中內(nèi)存涝焙,而托管綁定是通過堆創(chuàng)建的。

1.1代碼塊和指針函數(shù)

代碼塊借鑒了函數(shù)指針的語法赤兴,所以如果你知道如何聲明函數(shù)指針桶良,也就知道了如何聲明一個代碼塊

與函數(shù)指針類似艺普,代碼塊具有以下特征:

  • 返回類型可以手動聲明鉴竭,也可以由編譯器推導(dǎo)
  • 具有指定類型的參數(shù)列表
  • 擁有名稱
void (*my_func)(void);

這是非巢妫基礎(chǔ)的函數(shù)指針璧眠,他沒有參數(shù)和返回結(jié)果。只要把*換成^就可以把它轉(zhuǎn)換成一個代碼塊的定義了袁滥。

void (^my_func)(void);

在聲明代碼塊變量和代碼塊實現(xiàn)的開頭位置都要使用冪操作符题翻。與函數(shù)中一樣嵌赠,代碼塊的代碼要放在{}中。


示例:

int  (^square_black)(int number) = ^(int number) {
       return (number*number);
};
int result = square_black(5);
printf("Result = %d\n",result);

這個代碼塊獲取了一個整型參數(shù)并返回了這個數(shù)字的平方齿税。等號前面是代碼塊的定義凌箕,等號后面是實現(xiàn)內(nèi)容牵舱。

我們一般可以用如下關(guān)系來表示它們:

<returntype> (^blockname)(list of arguements) = ^(arguements){body;};

編譯器可以通過代碼塊的內(nèi)容推導(dǎo)出返回內(nèi)容仆葡,所以你可以省略它志笼。如果代碼塊沒有參數(shù)纫溃,也可以省略紊浩。

1.使用代碼塊

int result = square_block(5);
int value = 6;
int (^multiply_block)(int number) = ^(int number){
    return value*number;
};
int result = multiply_block(7);
printf("Result = %d\n",result);
  • 因為你將代碼塊聲明成了變量坊谁,所以你可以像函數(shù)一樣使用它滑臊。
  • 你可能注意到了雇卷,這行代碼中沒有冪符號关划,是因為只有在定義代碼塊的時候才需要使用它。
  • 代碼塊還有一個非晨泗妫酷的特性可用來代替原先的函數(shù):代碼塊可以訪問與它相同的(本地)有效范圍內(nèi)聲明的變量岛都,也就是說代碼塊可以訪問與它同時創(chuàng)建的有效變量臼疫。

2.直接使用代碼塊

NSArray *array = [NSArray arrayWithObjects:@"Amir",@"Mishal",@"Irrum",@"Adam",nil]
NSLog("Unsorted Array %@",array);
NSArray *sortedArray = [array sortedArrayUsingComparator:^(NSString *object1,NSString *object2){
      return [object1 compare:object2];
}];
NSLog("Sorted Array %@",sortedArray);
  • 使用代碼塊時通常不需要創(chuàng)建一個代碼塊變量烫堤,而是在代碼中內(nèi)聯(lián)代碼塊的內(nèi)容。
  • 通常拔创,你會需要一個將代碼塊作為參數(shù)的方法或函數(shù)剩燥。

3.使用typedef關(guān)鍵字

typedef double (^MKSampleMultiply2BlockRef)(double c,double d);

MKSampleMultiply2BlockRef multiply2 = ^(double c,double d){return c*d;};

printf("%f %f",multiply2(4,5),multiply2(5,2));
  • 如此長的定義語句讓人生畏灭红,而且易錯变擒,但是我們有typedef寝志。
  • 我們定義了一個名稱為MKSampleMultiply2BlockRef的代碼塊變量材部,它包含兩個雙浮點型參數(shù)并返回一個雙浮點型數(shù)值乐导。

4.代碼塊和變量
代碼塊被捕捉到后會捕捉創(chuàng)建點時的狀態(tài)兽叮。代碼塊可以訪問函數(shù)用到的標(biāo)準(zhǔn)類型的變量:

  • 全局變量鹦聪,包括在封閉范圍聲明的本地靜態(tài)變量。
  • 全局函數(shù)(明顯不是真實的變量)淘太。
  • 封閉范圍內(nèi)的參數(shù)蒲牧。
  • 函數(shù)級別(即與代碼塊聲明時相同的級別)的_block變量冰抢。他們是可以修改的變量挎扰。
  • 封閉范圍內(nèi)的非靜態(tài)變量會被獲取為常量。
  • Objective-C的實例變量尽超。
  • 代碼塊內(nèi)部的本地變量似谁。

5.本地變量

typedef double (^MKSampleMultiplyBlockRef)(void);
double a = 10,b = 20;
MKSampleMultiplyBlockRef multiply = ^(void){return a*b;};
NSLog(@"%f ",multiply());
a = 20;
b = 50;
NSLog(@"%f ",multiply());
  • 本地變量就是與代碼塊在同一范圍內(nèi)聲明的變量巩踏。
  • 因為變量是本地的蛀缝,代碼塊會在定義時復(fù)制并保存它們的狀態(tài),所以NSLog的輸出都是200嗤练。

6.全局變量

 typedef double (^MKSampleMultiplyBlockRef)(void);
 static double a = 10,b = 20;
 MKSampleMultiplyBlockRef multiply = ^(void){return a*b;};
 NSLog(@"%f ",multiply());
 a = 20;
 b = 50;
 NSLog(@"%f ",multiply());
  • 在上面的變量示例中煞抬,我們說過變量與代碼塊擁有相同的有效范圍革答,你可以根據(jù)需要把變量標(biāo)記為靜態(tài)的(全局)
  • 這樣残拐,第一次輸出 200溪食,第二次輸出1000

7.參數(shù)變量

typedef double (^MKSampleMultiply2BlockRef)(double c,double d);

MKSampleMultiply2BlockRef multiply2 = ^(double c,double d){return c*d;};

printf("%f %f",multiply2(4,5),multiply2(5,2));

代碼塊中的參數(shù)變量與函數(shù)中的參數(shù)變量具有相同的作用

8._block變量

double c = 3;
MKSampleMultiplyBlockRef multiply = ^(double a,double b){c = a*b};

報錯:Variable is not assignable (missing_block type specifier)
_block double c = 3;
MKSampleMultiplyBlockRef multiply = ^(double a,double b){c = a*b};
  • 本地變量會被代碼作為常量獲取到。如果你想要修改它們的值雀瓢,必須將它們聲明為可修改的刃麸,否則編譯會出錯
  • 如果想要修復(fù)這個編譯錯誤嫌蚤,你需要聽取前面編譯器的友好建議断傲,將變量c標(biāo)記為_block认罩。
  • 有些變量無法聲明為_block類型的垦垂,它們有兩個限制:沒有長度可變的數(shù)組劫拗,沒有包含可變長度數(shù)組的結(jié)構(gòu)體页慷。

9.代碼塊內(nèi)部的本地變量

void (^MKSampleBlockRef)(void) = ^(void){
      double a = 4;
      double c = 2;
      NSLog(@"%f",a*c);
};
MKSampleBlockRef();
**這些變量與函數(shù)中的本地變量具有相同的作用酒繁。**

1.2Objective-C變量

代碼塊是OC語言中的優(yōu)公民州袒,你可以像使用其它對象一樣使用它郎哭。使用時會遇到的最大問題就是內(nèi)存管理。
我們之前也說過邦蜜,在代碼塊中訪問OC變量時必須小心畦徘,以下規(guī)則能幫助你處理內(nèi)存管理:

  • 如果引用了一個OC對象井辆,必須要保留它杯缺。
  • 如果通過引用訪問了一個實例變量萍肆,要保留一次self(即執(zhí)行方法的對象)。
  • 如果通過數(shù)值訪問了一個實例變量包雀,變量需要保留才写。

示例:

NSString *string1 = ^{
  return [_theString stringByAppendingString:_theString];
};

_theString是聲明了代碼塊的類里面的實例變量赞草。因為在代碼塊中直接訪問了實例變量,所以包含它的對象(self)需要保留吆鹤。

NSString *localObject = _theString;
NSString *string2 = ^{
  return [localObject stringByAppendingString:localObject];
};

在這個例子中厨疙,我們是間接訪問:創(chuàng)建了一個指向?qū)嵗兞康谋镜匾貌⒃诖a塊里面使用。因此這次要保留的對象是localObject疑务,而不是self沾凄。


MKSampleVoidBlockRef block1 = ^{
  NSLog(@"Block1");
};
block1();

MKSampleVoidBlockRef block2 = ^{
  NSLog(@"Block2");
};
block2();

Block_release(block2);

block2 = Block_copy(block1);
block2();

因為代碼塊是對象,所以可以向它發(fā)送任何與內(nèi)存管理有關(guān)的消息暑始。在C語言級別中婴削,必須使用Block_copy()和Block_release()函數(shù)來適當(dāng)?shù)墓芾韮?nèi)存廊镜。

2并發(fā)性

  • 到目前為止,我們所討論過的所有代碼都是一個接著一個按照順序執(zhí)行的唉俗。
  • 用來運行Xcode的Mac電腦的處理器至少擁有兩個核心嗤朴,也可能更多。現(xiàn)在的最新iOS設(shè)備都是多核的虫溜。這意味著你可以在同一時間進(jìn)行多項任務(wù)雹姊。
  • 蘋果公司提供了多種可以利用多核特性的API。能夠在同一時間執(zhí)行多項任務(wù)的程序稱為并發(fā)的程序衡楞。
  • 利用并發(fā)性最基礎(chǔ)的方法是使用POSIX線程來處理程序的不同部分使其能夠獨立執(zhí)行吱雏。
  • 編寫并發(fā)性程序需要創(chuàng)建多個線程,因為線程是級別較低的API,你必須手動管理歧杏。根據(jù)硬件和其他軟件運行的環(huán)境镰惦,需要的線程數(shù)量會發(fā)生變化。
  • 為了減輕在多核上編程的負(fù)擔(dān)犬绒,蘋果公司引入了GCD(Grand Central Dispatch)旺入。這個技術(shù)減少了不少線程管理的麻煩,因此你可以集中精力編碼凯力。
  • 如果想要使用GCD茵瘾,你需要提交代碼塊或函數(shù)作為線程來運行。GCD是一個系統(tǒng)級別(system-level)的技術(shù)咐鹤,因此你可以在任意級別的代碼中使用它拗秘。GCD決定與要多少線程并安排它們運行的進(jìn)度。
  • 因為它們是運行在系統(tǒng)級別上的祈惶,所以可以平衡應(yīng)用程序所有內(nèi)容的加載聘殖,這樣可以提高計算機(jī)或者設(shè)備的執(zhí)行效率。

2.1同步

  • 我們該如何在由多核組成的通路中管理交通呢行瑞?可以使用同步裝置奸腺,比如在通道入口立一個標(biāo)記(flag)和一個互斥(mutex)。
  • mutex是mutual exclusion的縮寫血久,它指的是確保兩個線程不會在同一時間進(jìn)入臨界區(qū)突照。
@synchronized(theObject)
{
  //Critical section.
}
  • OC提供了一個語言級別的(language-level)關(guān)鍵字@synchronized。這個關(guān)鍵字擁有一個參數(shù)氧吐,通常這個對象是可以修改的讹蘑。它可以確保不同的線程會連續(xù)的訪問臨界區(qū)的代碼。
  • 若你定義了一個屬性并且沒有指定關(guān)鍵字nonatomic作為屬性的特性筑舅,編譯器會生成強(qiáng)制彼此互斥的getter和setter方法座慰。
  • 編譯器生成了@synchronized(mutex,atomic)語句來確保彼此互斥翠拣,這樣設(shè)置代碼和變量會產(chǎn)生一些消耗版仔,它會比直接訪問更慢一些。
  • 如果你不在意误墓,或者知道這些屬性值不會被多個線程訪問的話蛮粮,可以添加nonatomic特性,以提高性能谜慌。

1.選擇性能

  • 如果你只想讓一些代碼在后臺執(zhí)行然想,NSObject也提供了方法。

  • 這些方法的名字都有performSelector:欣范,最簡單的就是performSelectorInBackground:withObject:了变泄,他能在后臺執(zhí)行一個方法

  • 它通過一個創(chuàng)建一個線程來運行方法令哟。定義這些方法時必須遵從以下限制
    1.這些方法運行在各自的線程里面,因此你必須為這些Cocoa對象創(chuàng)建一個自動釋放池妨蛹,而主動釋放池是與主線程相關(guān)的励饵。
    2.這些方法不能有返回值,并且要么沒有參數(shù)滑燃,要么只有一個參數(shù)對象

//你只能使用以下代碼格式中的一種
- (void) myMethod;
- (void) myMethod:(id) myObject;

記住這些限制役听,我們實現(xiàn)的代碼應(yīng)該如下:

- (void) myBackgroundMethod {
    @autoreleasepool{
       NSLog(@"My Background Method");
    }
}

或者如下所示:

- (void) myOtherBackgroundMethod (id)myObject {
    @autoreleasepool{
       NSLog(@"My Background Method %@",myObject);
    }
}

如果想要在后臺執(zhí)行你的方法,只需要調(diào)動performSelectorInBackground:withObject:方法表窘,就像下面這樣:

[self performSelectorInBackground:@selector(myBackgroundMethod) withObject:nil];
[self performSelectorInBackground:@selector(myOtherBackgroundMethod) withObject:argumentObject];

當(dāng)方法執(zhí)行結(jié)束后典予,OC運行時會特地清理并棄掉線程。需要注意乐严,方法執(zhí)行結(jié)束后并不會通知你瘤袖。

2.調(diào)度隊列

GCD可以使用調(diào)度隊列(dispatch queue),它與線程很相似但使用起來更簡單昂验。只需要寫下你的代碼捂敌,把它指派為一個隊列,系統(tǒng)就會執(zhí)行它既琴。你可以同步或異步執(zhí)行任意代碼占婉。

一共有一下三種類型的隊列:

  • 連續(xù)隊列:每個連續(xù)隊列都會根據(jù)指派的順序執(zhí)行任務(wù)。你可以按自己的想法創(chuàng)建任意數(shù)量的隊列甫恩,它們會并行執(zhí)行任務(wù)逆济。
  • 并發(fā)隊列:每個并發(fā)隊列都能并發(fā)執(zhí)行一個或多個任務(wù)。任務(wù)會根據(jù)指派到隊列的順序開始執(zhí)行磺箕。你無法連續(xù)創(chuàng)建隊列奖慌,只能從系統(tǒng)提供的3個隊列內(nèi)選擇一個來使用。
  • 主隊列:它是應(yīng)用程序中有效的主隊列松靡,執(zhí)行的是應(yīng)用程序的主線程任務(wù)简僧。

死鎖:指的是兩個或多個任務(wù)在等待它方運行結(jié)束。

1.連續(xù)隊列
dispatch_queue_t my_serial_queue;
my_serial_queue = dispatch_queue_create("com.apress.MySerialQueue1",NULL);
  • 有時候有一連串任務(wù)需要按照一定的順序執(zhí)行雕欺,這時便可以使用連續(xù)隊列岛马。任務(wù)執(zhí)行順序為先入先出(FIFO):只要任務(wù)是異步提交的,隊列會確保任務(wù)根據(jù)預(yù)定順序執(zhí)行阅茶。這些隊列都是不會發(fā)生死鎖的蛛枚。
  • 第一個參數(shù)是隊列的名稱,第二個負(fù)責(zé)提供隊列的特性(現(xiàn)在用不到脸哀,所以必須時NULL)。
  • 當(dāng)隊列創(chuàng)建好之后扭吁,就可以給它指派任務(wù)撞蜂。因為隊列是引用計數(shù)的對象盲镶,所以等下我們還要討論內(nèi)存管理。

2.并發(fā)隊列

dispatch_queue_t myQueue蝌诡;
myQueue = dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
  • 并發(fā)調(diào)度隊列適用于那些可以并行運行的任務(wù)溉贿。并發(fā)隊列也遵從先入先出(FTFO)的規(guī)范,且任務(wù)可以在前一個任務(wù)結(jié)束前就開始執(zhí)行浦旱。
  • 一次運行的任務(wù)數(shù)量是無法預(yù)測的宇色,它會根據(jù)其它運行的任務(wù)在不同的時間變化所以你每運行同一個程序,并發(fā)任務(wù)的數(shù)量可能會是不一樣的颁湖。(如果需要確保每次運行的任務(wù)數(shù)量都是一樣的宣蠕,可以通過線程API來手動管理線程。)
  • 每個應(yīng)用程序都有三種并發(fā)隊列可以使用:高優(yōu)先級(high)甥捺,默認(rèn)優(yōu)先級(default)和低優(yōu)先級(low)抢蚀。如果想要引用它們,可以調(diào)用dispatch_get_global方法镰禾。
  • 其他優(yōu)先級的選項分別是DISPATCH_QUEUE_PRIORITY_HIGH和DISPATCH_QUEUE_PRIORITY_LOW皿曲。第二個參數(shù)暫時都用0。
  • 因為它們都是全局的吴侦,所以無需為它們管理內(nèi)存屋休。你不需要保留這些隊列的引用,在需要的時候使用函數(shù)來訪問就好了备韧。

3.主隊列

dispatch_queue_get_t main_queue = dispatch_get_current_queue(void);
  • 使用dispatch_get_main_queue 可以訪問與應(yīng)用程序主線程線管的連續(xù)隊列博投。
  • 因為這個隊列與主線程相關(guān),所以必須小心安排這個隊列中的任務(wù)順序盯蝴,否則它們可能會阻塞主應(yīng)用程序運行毅哗。
  • 通常要以同步方式使用這個隊列,提交多個任務(wù)并在它們操作完畢后執(zhí)行一些動作捧挺。

4.獲取當(dāng)前隊列

dispatch_queue_t myQueue = dispatch_get_current_queue();

你可以用過調(diào)用dispatch_get_current_queue()來找出當(dāng)前運行的隊列代碼塊虑绵。如果你在代碼塊對象之外調(diào)用了這個函數(shù),則它將會返回主隊列闽烙。

2.2隊列也要內(nèi)存管理

2.調(diào)度程序

添加任務(wù)的最簡單的的方法是通過代碼翅睛。代碼塊必須是dispatch_block_t這樣的類型,要定義沒有參數(shù)和返回值才行黑竞。

typedef void(^dispatch_block_t)(void)

先添加異步代碼塊捕发。這個函數(shù)擁有兩個參數(shù),分別是隊列和代碼塊很魂。

dispatch_async(_serial_queue,^{NSLog(@"Serial Task 1");});

如果你愿意的話扎酷,也可以定義一個代碼塊對象,而不是通過內(nèi)聯(lián)方式來創(chuàng)建遏匆。

dispatch_block_t myBlock = ^{NSLog(@"My Predfined block");};
dispatch_async(_serial_queue,myBlock);

之前說過法挨,我們也可以向隊列中添加函數(shù)谁榜。函數(shù)的標(biāo)準(zhǔn)原型必須要像下面這樣:

void function_name(void *arguement)

以下是示例函數(shù):

void myDispatchFuction(void *arguement){
    NSLog(@"Serial Task %@",(_bridge NSNumber *)arguement);
    NSMutableDictionary *context = (_bridge NSMutableDictionary *)dispatch_get_context(dispatch_get_current_queue());
    NSNumber *value = [context objectForKey:@"value"];
    NSLog(@"value = %@",value);
}

接下來需要向隊列添加這個函數(shù)。調(diào)度函數(shù)擁有三個參數(shù):隊列凡纳,需要傳遞的任意上下文以及函數(shù)窃植。如果你沒有信息要發(fā)送給還是你函數(shù),也可以只傳遞一個NULL值荐糜。

dispatch_async_f(_serial_queue,(_bridge void *)[NSNumber numberWithInt:3],(dispatch_function_t)myDispatchFuction);

隊列創(chuàng)建完之后巷怜,就做好接收任務(wù)的準(zhǔn)備了。當(dāng)我們添加了一個任務(wù)暴氏,隊列就會安排好它的進(jìn)度延塑。如果想要以同步方式添加到隊列中,請調(diào)用dispatch_sync_f函數(shù)偏序。

如果出于某個原因你想要暫停隊列页畦,請調(diào)用dispatch_susend()函數(shù)并傳遞隊列名稱。

dispatch_suspend(_serial_queue);

隊列暫停之后研儒,可以調(diào)用dispatch_resume()函數(shù)來重新啟用豫缨。這些全都有你來掌控。

dispatch_resume(_serial_queue);

2.3操作隊列

  • 這些東西的層級都很低端朵,你一定想要知道怎樣能讓它在OC中使用好芭。
  • 實際上,有一些被稱為操作的API冲呢,可以讓隊列在OC層級上使用起來更加簡單舍败。
  • 如果想要使用操作,首先需要創(chuàng)建一個操作對象敬拓,然后將其指派給操作隊列邻薯,并讓隊列執(zhí)行它。一共有三種創(chuàng)建操作的方式乘凸。
    1.NSInvocationOperation:如果你已經(jīng)擁有一個可以完成工作的類厕诡,并且想要在隊列上執(zhí)行,可以嘗試使用這種方法营勤。
    2.NSBlockOperation:這有些像包含了需要執(zhí)行代碼塊的dispatch_async函數(shù)灵嫌。
    3.自定義的操作:如果你需要更靈活的操作類型,可以創(chuàng)建自己的自定義類型葛作。你必須通過NSOperation子類來定義你的操作寿羞。

創(chuàng)建調(diào)用操作

NSInvocationOperation會為執(zhí)行任務(wù)的類調(diào)用選擇器。因此赂蠢,如果你擁有一個包含所需方法的類绪穆,使用這種方式創(chuàng)建會非常方便。

@implementation MyCustomClass
- (NSOperation *)operationWithData:(id)data{
    return[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(myWorkerMethod:) object:data];
}
//This is the method that does the actual work
- (void)myWorkerMethod:(id)data{
   NSLog(@"My Worker Method %@",data);
}
@end

一旦向隊列添加了操作,任務(wù)即將執(zhí)行時便會調(diào)用類里面的myWorkermethod:方法霞幅。

  • 創(chuàng)建代碼塊操作
    如果你有一個需要執(zhí)行的代碼塊漠吻,那么可以創(chuàng)建這個操作并讓隊列執(zhí)行它量瓜。
NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
   //Do my work
}];

這些操作的代碼塊與我們在調(diào)度隊列中使用的是同一種類型司恳。一旦創(chuàng)建了第一個代碼塊操作,你便可以通過addExecutionBlock:方法繼續(xù)添加更多的代碼塊绍傲。根據(jù)隊列的類型(連續(xù)的或并發(fā)的)代碼塊會分別以連續(xù)或并行的方式運行扔傅。

[blockOperation addExecutionBlock:^{
   //do my work
}];
  • 向隊列中添加操作
    1.一旦創(chuàng)建了操作,你就需要向隊列中添加代碼塊烫饼。這次我們將使用NSOperationQueue來取代之前使用的dispatch_queue_t函數(shù)猎塞。NSOperationQueue一般會并發(fā)執(zhí)行操作。它具有相關(guān)性杠纵,因此如果某操作是基于其它操作的荠耽,它們會相應(yīng)的執(zhí)行。
    2.如果要確保你的操作是連續(xù)執(zhí)行的比藻,可以設(shè)置最大并發(fā)操作數(shù)為1铝量,這樣任務(wù)將會按照先入先出的規(guī)范執(zhí)行。在向隊列添加操作之前银亲,需要某個方法來引用到那個隊列慢叨。你可以創(chuàng)建一個新的隊列或使用之前已經(jīng)定義過的隊列(比如當(dāng)前運行的隊列):NSOperationQueue *currentQueue = [NSOperationQueue currentQueue];或主隊列:NSOperationQueue *mainQueue = [NSOperationQueue mainqueue];

以下就是我們創(chuàng)建自己隊列的代碼:

NSOperationQueue *_operationQueue = [[NSOperationQueue alloc] init];

現(xiàn)在我們擁有了一個隊列,可以使用addOperation:來添加操作:

[theQueue addOperation:blockOperation];

也可以添加需要執(zhí)行的代碼塊來代替操作對象:

[theQueue addOperationWithBlock:^{
   NSLog(@"My Block");
}];

一旦向隊列中添加了操作务蝠,他就會被安排進(jìn)度并執(zhí)行拍谐。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市馏段,隨后出現(xiàn)的幾起案子轩拨,更是在濱河造成了極大的恐慌,老刑警劉巖院喜,帶你破解...
    沈念sama閱讀 222,729評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件亡蓉,死亡現(xiàn)場離奇詭異,居然都是意外死亡够坐,警方通過查閱死者的電腦和手機(jī)寸宵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來元咙,“玉大人梯影,你說我怎么就攤上這事∈悖” “怎么了甲棍?”我有些...
    開封第一講書人閱讀 169,461評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長赶掖。 經(jīng)常有香客問我感猛,道長七扰,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,135評論 1 300
  • 正文 為了忘掉前任陪白,我火速辦了婚禮颈走,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘咱士。我一直安慰自己立由,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 69,130評論 6 398
  • 文/花漫 我一把揭開白布序厉。 她就那樣靜靜地躺著锐膜,像睡著了一般。 火紅的嫁衣襯著肌膚如雪弛房。 梳的紋絲不亂的頭發(fā)上道盏,一...
    開封第一講書人閱讀 52,736評論 1 312
  • 那天,我揣著相機(jī)與錄音文捶,去河邊找鬼荷逞。 笑死,一個胖子當(dāng)著我的面吹牛拄轻,可吹牛的內(nèi)容都是我干的颅围。 我是一名探鬼主播,決...
    沈念sama閱讀 41,179評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼恨搓,長吁一口氣:“原來是場噩夢啊……” “哼院促!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起斧抱,我...
    開封第一講書人閱讀 40,124評論 0 277
  • 序言:老撾萬榮一對情侶失蹤常拓,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后辉浦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體弄抬,經(jīng)...
    沈念sama閱讀 46,657評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,723評論 3 342
  • 正文 我和宋清朗相戀三年宪郊,在試婚紗的時候發(fā)現(xiàn)自己被綠了掂恕。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,872評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡弛槐,死狀恐怖懊亡,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情乎串,我是刑警寧澤店枣,帶...
    沈念sama閱讀 36,533評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響鸯两,放射性物質(zhì)發(fā)生泄漏闷旧。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,213評論 3 336
  • 文/蒙蒙 一钧唐、第九天 我趴在偏房一處隱蔽的房頂上張望忙灼。 院中可真熱鬧,春花似錦逾柿、人聲如沸缀棍。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至父腕,卻和暖如春弱匪,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背璧亮。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評論 1 274
  • 我被黑心中介騙來泰國打工萧诫, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人枝嘶。 一個月前我還...
    沈念sama閱讀 49,304評論 3 379
  • 正文 我出身青樓帘饶,卻偏偏與公主長得像,于是被迫代替她去往敵國和親群扶。 傳聞我的和親對象是個殘疾皇子及刻,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,876評論 2 361

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