Block åéæ¥æ blocks çå¼ç¨ãä½ å¯ä»¥ä½¿ç¨å声æ
å½æ°æé类似çè¯æ³æ¥å£°æå® ä»¬,é¤äºå®ä»¬ä½¿ç¨^修饰符æ¥æ¿ä»£ * 修饰符ãBlock ç±»åå¯ä»¥å®å
¨æä½å
¶ä» C ç³»ç» ç±»åã以ä¸é½æ¯åæ³ç block 声æ:
void (^blockReturningVoidWithVoidArgument)(void);
int (^blockReturningIntWithIntAndCharArguments)(int, char);
void (^arrayOfTenBlocksReturningVoidWithIntArgument[10])(int);
Blocks è¿æ¯æå¯ååæ°(...)ãä¸ä¸ªæ²¡æ使ç¨ä»»ä½åæ°ç block å¿
é¡»å¨åæ°å表 ä¸é¢ç¨ void æ æã
Blocks 被设计为类åå®å
¨ç,å®éè¿ç»
ç¼è¯å¨å®æ´ç
å
æ°æ®æ¥åæ³ä½¿ç¨ blocksã ä¼ éå° blocks çåæ°ååé
ç
è¿åå¼ãä½ å¯ä»¥æä¸ä¸ª block å¼ç¨å¼ºå¶è½¬æ¢ä¸ºä»»æç±»å çæé,åä¹äº¦ç¶ãä½æ¯ä½ ä¸è½éè¿ä¿®é¥°ç¬¦ * æ¥è§£å¼ç¨ä¸ä¸ª block,å æ¤ä¸ä¸ª block ç大å°æ¯æ æ³å¨ç¼è¯çæ¶å计ç®çã
ä½ åæ ·å¯ä»¥å建 blocks çç±»åãå½ä½ å¨å¤ä¸ªå°æ¹ä½¿ç¨åä¸ä¸ªç»å®çç¾åç block æ¶,è¿é常被认为æ¯æä½³çåæ³ã
typedef float (^MyBlockType)(float, float);
MyBlockType myFirstBlock = // ... ;
MyBlockType mySecondBlock = // ... ;
3.2 å建ä¸ä¸ªblock
ä½ å¯ä»¥ä½¿ç¨ ^ 修饰符æ¥æ è¯ä¸ä¸ª block
表达å¼çå¼å§ãå®é常åé¢è·çä¸ä¸ªè¢« () å
å«èµ·æ¥çåæ°å表ãBlock ç主ä½ä¸è¬è¢«å
å«å¨ {} éé¢ãä¸é¢ç示ä¾å®ä¹äºä¸ä¸ª ç®åç block,并æå®èµå¼ç»åé¢å£°æçåé(oneFrom)ãè¿é block 使ç¨ä¸ä¸ªæ å C çç»æ符 ; æ¥ç»æã
int (^oneFrom)(int);
oneFrom = ^(int anInt) {
return anInt - 1;
};
å¦æä½ æ²¡ææ¾å¼çç» block 表达å¼å£°æä¸ä¸ªè¿åå¼,å®ä¼èªå¨çä» block å
å®¹æ¨ æåºæ¥ãå¦æè¿åå¼æ¯æ¨æç,èä¸åæ°å表ä¹æ¯ void,é£ä¹ä½ åæ ·å¯ä»¥çç¥åæ°å 表ç voidãå¦ææè
å½åºç°å¤ä¸ªè¿åç¶æçæ¶å,å®ä»¬å¿
é¡»æ¯å®å
¨å¹é
ç(å¦ææå¿
è¦å¯ä»¥ä½¿ç¨å¼ºå¶è½¬æ¢)ã
3.3 å
¨å±blocks
å¨æ件级å«,ä½ å¯ä»¥æ block ä½ä¸ºå
¨å±æ 示符:
#import
int GlobalInt = 0;
int (^getGlobalInt)(void) = ^{ return GlobalInt; };
第åç« Blocksååé
æ¬ææè¿° blocks ååéä¹é´ç交äº,å
æ¬å
å管çã
ä½ å¯ä»¥å¼ç¨ä¸ç§æ åç±»åçåé,å°±åä½ å¨å½æ°éé¢å¼ç¨é£æ ·:
å
¨å±åé,å
æ¬éæå±é¨åéã
å
¨å±å½æ°(å¨ææ¯ä¸èè¨è¿ä¸æ¯åé)ã
å°éèå´å
çå±é¨åéååæ°ã
Blocks åæ ·æ¯æå
¶ä»ä¸¤ç§ç±»åçåé:
å¨å½æ°çº§å«æ¯__blockåéãè¿äºå¨blockéé¢æ¯å¯åç(åå°éèå´),并任ä½å¼
ç¨ block çé½è¢«ä¿åä¸ä»½å¯æ¬å°å éé¢ã
å¼å
¥constã
æå,å¨å®ç°æ¹æ³éé¢,blocksä¹è®¸ä¼å¼ç¨Objective-Cçå®ä¾åéãåé
â对象
å Block åéâé¨åã
å¨ block éé¢ä½¿ç¨åééµå¾ªä»¥ä¸è§å:
å
¨å±åéå¯è®¿é®,å
æ¬å¨ç¸åä½ç¨åèå´å
ç
éæåéã
ä¼ éç»blockçåæ°å¯è®¿é®(åå½æ°çåæ°ä¸æ ·)ã
ç¨åºéé¢å±äºåä¸ä½ç¨åèå´çå (ééæç)åéä½ä¸ºconståé(å³åªè¯»)ã
å®ä»¬çå¼å¨ç¨åºéé¢ç block 表达å¼å
使ç¨ãå¨åµå¥ block éé¢,该å¼å¨æè¿ç
å°éèå´å
被æè·ã
å±äºåä¸ä½ç¨åèå´å
并被__blockåå¨ä¿®é¥°ç¬¦æ è¯çåéä½ä¸ºå¼ç¨ä¼ éå æ¤æ¯
å¯åçã
å±äºåä¸ä½ç¨åèå´å
blockçåé,å°±åå½æ°çå±é¨åéæä½ä¸æ ·ã
æ¯æ¬¡è°ç¨ block é½æä¾äºåéçä¸ä¸ªæ·è´ãè¿äºåéå¯ä»¥ä½ä¸º const æ¥ä½¿ç¨,æå¨ block å°éèå´å
ä½ä¸ºå¼ç¨åéã
ä¸é¢çä¾åæ¼ç¤ºäºä½¿ç¨æ¬å°ééæåé:
int x = 123;
void (^printXAndY)(int) = ^(int y) {
printf("%d %d\n", x, y);
};
printXAndY(456); // prints: 123 456
æ£å¦ä¸é¢æå°ç,å¨ block å
è¯å¾ç» x èµä¸ä¸ªæ°å¼ä¼å¯¼è´é误åç:
int x = 123;
void (^printXAndY)(int) = ^(int y) {
x = x + y; // error
printf("%d %d\n", x, y);
};
为äºå¯ä»¥å¨ block å
ä¿®æ¹ä¸ä¸ªåé,ä½ éè¦ä½¿ç¨__block åå¨ç±»å修饰符æ¥æ è¯è¯¥ åéãåé
â__block åå¨ç±»åâé¨åã
4.2 __blockåå¨ç±»å
ä½ å¯ä»¥æå®å¼å
¥ä¸ä¸ªåé为å¯æ´æ¹ç,å³è¯»-åç,éè¿åºç¨__block åå¨ç±»åä¿® 饰符ãå±é¨åéç__block çåå¨å registerãautoãstatic çåå¨ç±»åç¸ä¼¼,ä½å®ä»¬ä¹ é´ä¸å
¼å®¹ã
__block åéä¿åå¨åéå
±äº«çä½ç¨åèå´å
,ææç blocks å block å¯æ¬é½å£°æ æå建å¨ååéçä½ç¨åç¸åèå´å
ãæ以,å¦æä»»ä½ blocks å¯æ¬å£°æå¨æ å
并æªè¶
åºæ çç»ææ¶,该åå¨ä¼è®©æ 帧å
äºè¢«ç ´å(æ¯å¦å°è£
为以åæ§è¡)ãåä¸ä½ç¨åè å´å
ç»å®çå¤ä¸ª block å¯ä»¥åæ¶ä½¿ç¨ä¸ä¸ªå
±äº«åéã
ä½ä¸ºä¸ç§ä¼å,blockåå¨å¨æ ä¸é¢,å°±åblocksæ¬èº«ä¸æ ·ãå¦æ使ç¨Block_copy æ·è´äº block çä¸ä¸ªå¯æ¬(æè
å¨ Objective-C éé¢ç» block åéäºä¸æ¡ copy æ¶æ¯), åéä¼è¢«æ·è´å°å ä¸é¢ãæ以ä¸ä¸ª__block åéçå°åå¯ä»¥éæ¶é´æ¨ç§»è被æ´æ¹ã
使ç¨__block çåéæ两个éå¶:å®ä»¬ä¸è½æ¯å¯åé¿çæ°ç»,并ä¸å®ä»¬ä¸è½æ¯å
å«æ C99 å¯åé¿åº¦çæ°ç»åéç
æ°æ®ç»æã
以ä¸ä¸¾ä¾è¯´æäºå¦ä½ä½¿ç¨__block åé:
__block int x = 123; // x lives in block storage
void (^printXAndY)(int) = ^(int y) {
x = x + y;
printf("%d %d\n", x, y);
};
printXAndY(456); // prints: 579 456
// x is now 579
ä¸é¢çä¾åæ¾ç¤ºäº blocks åå
¶ä»å 个类ååéé´ç交äº:
extern NSInteger CounterGlobal;
static NSInteger CounterStatic;
{
NSInteger localCounter = 42;
__block char localCharacter;
void (^aBlock)(void) = ^(void) {
++CounterGlobal;
++CounterStatic;
CounterGlobal = localCounter; // localCounter fixed at block creation
localCharacter = 'a'; // sets localCharacter in enclosing scope
};
++localCounter; // unseen by the block
localCharacter = 'b';
aBlock(); // execute the block
// localCharacter now 'a'
}
4.3 对象(Object)åBlockåé
Block æä¾äºæ¯æ Objective-C å Objective-C++ç对象,åå
¶ä» blocks çåéã
4.3.1 Objective-C对象
å¨å¼ç¨è®¡æ°çç¯å¢éé¢,é»è®¤æ
åµä¸å½ä½ å¨ block éé¢å¼ç¨ä¸ä¸ª Objective-C 对象çæ¶ å,该对象ä¼è¢«retainãå½ä½ ç®åçå¼ç¨äºä¸ä¸ªå¯¹è±¡çå®ä¾åéæ¶,å®åæ ·è¢« retainã ä½æ¯è¢«__block åå¨ç±»å修饰符æ è®°ç对象åéä¸ä¼è¢« retain. 注æ:å¨åå¾åæ¶æºå¶éé¢,å¦æä½ åæ¶ä½¿ç¨__weak å__block æ¥æ è¯ä¸ä¸ªåé,é£ä¹è¯¥ block å°ä¸ä¼ä¿è¯å®æ¯ä¸ç´æ¯ææçã
å¦æä½ å¨å®ç°æ¹æ³çæ¶å使ç¨äº block,对象çå
å管çè§åæ´å¾®å¦:
å¦æä½ éè¿å¼ç¨æ¥è®¿é®ä¸ä¸ªå®ä¾åé,self ä¼è¢« retainã
å¦æä½ éè¿å¼æ¥è®¿é®ä¸ä¸ªå®ä¾åé,é£ä¹åéä¼è¢« retainã
ä¸é¢ä¸¾ä¾è¯´æ两个æ¹å¼çä¸å:
dispatch_async(queue, ^{
// instanceVariable is used by reference, self is retained
doSomethingWithObject(instanceVariable);
});
id localVariable = instanceVariable;
dispatch_async(queue, ^{
// localVariable is used by value, localVariable is retained (not self)
doSomethingWithObject(localVariable);
4.3.2 C++对象
éå¸¸ä½ å¯ä»¥å¨ block å
ä½¿ç¨ C++ç对象ãå¨æåå½æ°éé¢,éè¿éå¼ç导å
¥ this æéå¼ç¨æååéåå½æ°,ç»æä¼å¾å¾®å¦ãæ两个æ¡ä»¶å¯ä»¥è®© block 被æ·è´:
å¦æä½ æ¥æ__blockåå¨çç±»,å®æ¬æ¥æ¯ä¸ä¸ªåºäºæ çC++对象,é£ä¹é常ä¼ä½¿ç¨ copy ç
æé å½æ°ã
å¦æä½ å¨ block éé¢ä½¿ç¨ä»»ä½å
¶ä» C++åºäºæ ç对象,å®å¿
é¡»å
å«ä¸ä¸ª const copy çæé å½æ°ã该 C++对象使ç¨è¯¥æé å½æ°æ¥æ·è´ã
4.3.3 Blocks
å½ä½ æ·è´ä¸ä¸ª block æ¶,ä»»ä½å¨è¯¥ block éé¢å¯¹å
¶ä» blocks çå¼ç¨é½ä¼å¨éè¦ç æ¶å被æ·è´,å³æ·è´æ´ä¸ªç®å½æ (ä»é¡¶é¨å¼å§)ãå¦æä½ æ block åé并å¨è¯¥ block é é¢å¼ç¨å
¶ä»ç block,é£ä¹é£ä¸ªå
¶ä»ç block ä¼è¢«æ·è´ä¸ä»½ã
å½ä½ æ·è´ä¸ä¸ªåºäºæ ç block æ¶,ä½ ä¼è·å¾ä¸ä¸ªæ°ç blockãä½æ¯å¦æä½ æ·è´ä¸ä¸ª åºäºå ç block,ä½ åªæ¯ç®åçéå¢äºè¯¥ block çå¼ç¨æ°,并æåå§ç block ä½ä¸ºå½æ° ææ¹æ³çè¿åå¼ã
äºç« 使ç¨Blocks
5.1 è°ç¨ä¸ä¸ªBlock
å¦æä½ å£°æäºä¸ä¸ª block ä½ä¸ºåé,ä½ å¯ä»¥æå®ä½ä¸ºä¸ä¸ªå½æ°æ¥ä½¿ç¨,å¦ä¸é¢ç
两个ä¾åæ示:
int (^oneFrom)(int) = ^(int anInt) {
return anInt - 1;
};
printf("1 from 10 is %d", oneFrom(10));
// Prints "1 from 10 is 9"
float (^distanceTraveled) (float, float, float) =
^(float startingSpeed, float acceleration, float time) {
float distance = (startingSpeed * time) + (0.5 * acceleration * time * time);
return distance;
};
float howFar = distanceTraveled(0.0, 9.8, 1.0);
// howFar = 4.9
ç¶èä½ é常ä¼æ block ä½ä¸ºåæ°ä¼ éç»ä¸ä¸ªå½æ°ææ¹æ³ãå¨è¿ç§æ
åµä¸,ä½ éè¿ éè¦å建ä¸ä¸ªâå
è(inline)âç blockã
5.2 使ç¨Blockä½ä¸ºå½æ°çåæ°
ä½ å¯ä»¥æä¸ä¸ª block ä½ä¸ºå½æ°çåæ°å°±åå
¶ä»ä»»ä½åæ°é£æ ·ãç¶èå¨å¾å¤æ
åµä¸, ä½ ä¸éè¦å£°æblocks;ç¸åä½ åªè¦ç®åå¨éè¦å®ä»¬ä½ä¸ºåæ°çå°æ¹å
èå®ç°å®ä»¬ãä¸ é¢çä¾åä½¿ç¨ qsort_b å½æ°ãqsort_b åæ å qsort_r å½æ°ç±»ä¼¼,ä½æ¯å®æåä¸ä¸ªåæ°ç¨ block.
char *myCharacters[3] = { "TomJohn", "George", "Charles Condomine"};
qsort_b(myCharacters, 3, sizeof(char *), ^(const void *l, constvoid *r) {
char *left = *(char **)l;
char *right = *(char **)r;
return strncmp(left, right, 1);
});
// Block implementation ends at "}"
// myCharacters is now { "Charles Condomine", "George", "TomJohn" }
注æå½æ°åæ°å表å
å«äºä¸ä¸ª blockã
ä¸ä¸ä¸ªä¾åæ¾ç¤ºäºå¦ä½å¨ dispatch_apply å½æ°éé¢ä½¿ç¨ blockãdispatch_apply 声æ å¦ä¸:
void dispatch_apply(size_t iterations, dispatch_queue_t queue, void(^block)(size_t));
该å½æ°æ交ä¸ä¸ª block ç»æ¹å¤çéåæ¥å¤æ¬¡è°ç¨ãå®éè¦ä¸ä¸ªåæ°;第ä¸ä¸ªæå® è¿ä»£å¨çæ°é;第äºä¸ªæå®ä¸ä¸ªè¦æ交 block çéå;第ä¸ä¸ªæ¯ block å®æ¬èº«,å®èª å·±éè¦ä¸ä¸ªåæ°(å½åè¿ä»£å¨çä¸æ )ã
ä½ å¯ä»¥ä½¿ç¨ dispatch_apply æ¥ç®åçæå°åºè¿ä»£å¨çä¸æ ,å¦ä¸:
#include
size_t count = 10;
dispatch_queue_t queue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply(count, queue, ^(size_t i) {
printf("%u\n", i);
});
5.3 使ç¨Blockä½ä¸ºæ¹æ³çåæ°
Cocoa æä¾äºä¸ç³»åä½¿ç¨ block çæ¹æ³ãä½ å¯ä»¥æä¸ä¸ª block ä½ä¸ºæ¹æ³çåæ°å°±å å
¶ä»åæ°é£æ ·ã
ä¸é¢çä¾åç¡®å®æ°ç»åé¢äºä¸ªå
ç´ ä¸ç¬¬ä¸ä¸ªåºç°å¨ç»å®çè¿æ»¤å¨éä¸ä»»ä½ä¸ä¸ª çä¸æ ã
NSArray *array = [NSArray arrayWithObjects: @"A", @"B", @"C", @"A",@"B", @"Z",@"G", @"are", @"Q", nil];
NSSet *filterSet = [NSSet setWithObjects: @"A", @"Z", @"Q", nil];
BOOL (^test)(id obj, NSUInteger idx, BOOL *stop);
test = ^ (id obj, NSUInteger idx, BOOL *stop) {
if (idx < 5) {
if ([filterSet containsObject: obj]) {
return YES;
}
}
return NO;
};
NSIndexSet *indexes = [array indexesOfObjectsPassingTest:test];
NSLog(@"indexes: %@", indexes);
ä¸é¢çä¾åç¡®å®ä¸ä¸ª NSSet æ¯å¦å
å«ä¸ä¸ªç±å±é¨åéæå®çåè¯,并ä¸å¦ææ¡ä»¶ æç«æå¦å¤ä¸ä¸ªå±é¨åé(found)设置为 YES(并åæ¢æç´¢)ã注æå° found åæ¶è¢«å£° æ为__block åé,并ä¸è¯¥ block æ¯å
èå®ä¹ç:
__block BOOL found = NO;
NSSet *aSet = [NSSet setWithObjects: @"Alpha", @"Beta", @"Gamma",@"X", nil];
NSString *string = @"gamma";
[aSet enumerateObjectsUsingBlock:^(id obj, BOOL *stop) {
if ([obj localizedCaseInsensitiveCompare:string] == NSOrderedSame) {
*stop = YES;
found = YES;
}
}];
// At this point, found == YES
5.4 æ·è´Blocks
é常,ä½ ä¸éè¦ copy(æ retain)ä¸ä¸ª block.å¨ä½ å¸æ block å¨å®è¢«å£°æçä½ç¨å 被éæ¯å继ç»ä½¿ç¨çè¯,ä½ åéè¦åä¸ä»½æ·è´ãæ·è´ä¼æ block 移å°å éé¢ã
ä½ å¯ä»¥ä½¿ç¨ C å½æ°æ¥ copy å release ä¸ä¸ª block:
Block_copy();
Block_release();
å¦æä½ ä½¿ç¨ Objective-C,ä½ å¯ä»¥ç»ä¸ä¸ª block åé copyãretain å release(æ autorelease)æ¶æ¯ã
为äºé¿å
å
åæ³é²,ä½ å¿
é¡»æ»æ¯å¹³è¡¡ Block_copy()å Block_release()ãä½ å¿
须平衡 copy æ retain årelease(æ autorelease)--é¤éæ¯å¨åå¾åæ¶çç¯å¢éé¢ã
5.5 éè¦é¿å
ç模å¼
ä¸ä¸ª block çææ¬(é常æ¯^{...})æ¯ä¸ä¸ªä»£è¡¨ block çæ¬å°æ æ°æ®ç»æå°åã å æ¤è¯¥æ¬å°æ æ°æ®ç»æçä½ç¨èå´æ¯å°éçå¤åç¶æ,æä»¥ä½ åºè¯¥é¿å
ä¸é¢ä¾åæ¾ç¤º ç模å¼:
void dontDoThis() {
void (^blockArray[3])(void); // an array of 3 block references
for (int i = 0; i < 3; ++i) {
blockArray[i] = ^{ printf("hello, %d\n", i); };
// WRONG: The block literal scope is the "for" loop
}
}
void dontDoThisEither() {
void (^block)(void);
int i = random():
if (i > 1000) {
block = ^{ printf("got i at: %d\n", i); };
// WRONG: The block literal scope is the "then" clause
}
// ...
}
5.6 è°è¯
ä½ å¯ä»¥å¨ blocks éé¢è®¾ç½®æç¹å¹¶åæ¥è°è¯ãä½ å¯ä»¥å¨ä¸ä¸ª GDB ç对è¯éé¢ä½¿ç¨
invoke-block æ¥è°ç¨ä¸ä¸ª blockãå¦ä¸é¢çä¾åæ示:
$ invoke-block myBlock 10 20
å¦æä½ æ³ä¼ éä¸ä¸ª C å符串,ä½ å¿
é¡»ç¨å¼å·æ¬è¿å®ãä¾å¦,为äºä¼ é this string ç»doSomethingWithString ç block,ä½ å¯ä»¥ç±»ä¼¼ä¸é¢è¿æ ·å:
$ invoke-block doSomethingWithString ""this string""
ç»æè¯
Block æ¯ iOS 4.0 ä¹åæ·»å çæ°ç¹æ§æ¯æãæ¬äººäº²æµæè§ä½¿ç¨ Block æ大ç便å©å°± æ¯ç®åçåè°è¿ç¨ã以åä½¿ç¨ UIView çå¨ç»,è¿ç¨è¦æ§å¶å¨ç»ç»æåè¿è¡ç¸åºçå¤ çãiOS 4.0 ä¹å,UIView æ°å¢äºå¯¹ Block çæ¯æ,ç°å¨åªè¦ä½¿ç¨ç®åçä¸ä¸ª Block 代ç å°±å¯ä»¥å¨åå¨ç»ç代ç é¨åç´æ¥æ·»å å¨ç»ç»æåçæä½ãè¿æå°±æ¯å¨ä½¿ç¨Notification æ¶å Block ä¹é常æ帮å©ãåæ£å¤ç¨å°±å¯ä»¥ä½ä¼å° Blockçä¼ç¾äºã
对äº,ä½¿ç¨ Block è¦è°¨è®°å«é æ对象äºç¸å¼ç¨å¯¹æ¹å¯¼è´å¼ç¨è®¡æ°è¿å
¥ä¸ä¸ªå¾ªç¯å¯¼ è´å¯¹è±¡æ æ³è¢«éæ¾ãiOS 5.0 ä¹åç ARC ä¹æ¯æ æ³è§£å³è¯¥æ½å¨çäºç¸å¼ç¨çé®é¢çã æ以å Block çæ¶åè¦æ³¨æè¿ç¹ãå 为 Block å¾å¾å¨åå°èªå¨å¯¹ä¸äºå®å¼ç¨äºç对象 è¿è¡ retain æä½ãå
·ä½å½¢å¼è¿éå°±ä¸è·ç¦»äº,大家å¨ä½¿ç¨çæ¶åå¤ä½ä¼ä¸ä¸ã