您的位置:首页 > 移动开发 > IOS开发

IOS Dev Intro - Blocks Programming Series 05

2016-06-12 10:22 267 查看
https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Blocks/Articles/bxUsing.html#//apple_ref/doc/uid/TP40007502-CH5-SW1


UsingBlocks


InvokingaBlock

Ifyoudeclareablockasavariable,youcanuseitasyouwouldafunction,asshowninthesetwoexamples:

int(^oneFrom)(int)=^(intanInt){

returnanInt-1;

};


printf("1from10is%d",oneFrom(10));

//Prints"1from10is9"


float(^distanceTraveled)(float,float,float)=

^(floatstartingSpeed,floatacceleration,floattime){


floatdistance=(startingSpeed*time)+(0.5*acceleration*time*time);

returndistance;

};


floathowFar=distanceTraveled(0.0,9.8,1.0);

//howFar=4.9

Frequently,however,youpassablockastheargumenttoafunctionoramethod.Inthesecases,youusuallycreateablock“inline”.


UsingaBlockasaFunctionArgument

Youcanpassablockasafunctionargumentjustasyouwouldanyotherargument.Inmanycases,however,youdon’tneedtodeclareblocks;insteadyousimplyimplementtheminlinewherethey’rerequiredasan
argument.Thefollowingexampleusesthe 
qsort_b
 function. 
qsort_b
 is
similartothestandard 
qsort_r
 function,buttakesablockasitsfinalargument.

char*myCharacters[3]={"TomJohn","George","CharlesCondomine"};


qsort_b(myCharacters,3,sizeof(char*),^(constvoid*l,constvoid*r){

char*left=*(char**)l;

char*right=*(char**)r;

returnstrncmp(left,right,1);

});

//Blockimplementationendsat"}"


//myCharactersisnow{"CharlesCondomine","George","TomJohn"}

Noticethattheblockiscontainedwithinthefunction’sargumentlist.
Thenextexampleshowshowtouseablockwiththe 
dispatch_apply
 function. 
dispatch_apply
 is
declaredasfollows:

voiddispatch_apply(size_titerations,dispatch_queue_tqueue,void(^block)(size_t));

Thefunctionsubmitsablocktoadispatchqueueformultipleinvocations.Ittakesthreearguments;thefirstspecifiesthenumberofiterationstoperform;thesecondspecifiesaqueuetowhichtheblockis
submitted;andthethirdistheblockitself,whichinturntakesasingleargument—thecurrentindexoftheiteration.
Youcanuse 
dispatch_apply
 triviallyjusttoprintouttheiterationindex,asshown:

#include<dispatch/dispatch.h>

size_tcount=10;

dispatch_queue_tqueue=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);


dispatch_apply(count,queue,^(size_ti){

printf("%u\n",i);

});


UsingaBlockasaMethodArgument

Cocoa provides
anumberofmethodsthatuseblocks.Youpassablockasamethodargumentjustasyouwouldanyotherargument.
Thefollowingexampledeterminestheindexesofanyofthefirstfiveelementsinanarraythatappearinagivenfilterset.

NSArray*array=@[@"A",@"B",@"C",@"A",@"B",@"Z",@"G",@"are",@"Q"];

NSSet*filterSet=[NSSetsetWithObjects:@"A",@"Z",@"Q",nil];


BOOL(^test)(idobj,NSUIntegeridx,BOOL*stop);


test=^(idobj,NSUIntegeridx,BOOL*stop){


if(idx<5){

if([filterSetcontainsObject:obj]){

returnYES;

}

}

returnNO;

};


NSIndexSet*indexes=[arrayindexesOfObjectsPassingTest:test];


NSLog(@"indexes:%@",indexes);


/*

Output:

indexes:<NSIndexSet:0x10236f0>[numberofindexes:2(in2ranges),indexes:(03)]

*/

Thefollowingexampledetermineswhetheran 
NSSet
 objectcontainsawordspecifiedbyalocalvariableand
setsthevalueofanotherlocalvariable(
found
)to 
YES
 (and
stopsthesearch)ifitdoes.Noticethat 
found
 isalsodeclaredasa 
__block
 variable,
andthattheblockisdefinedinline:

__blockBOOLfound=NO;

NSSet*aSet=[NSSetsetWithObjects:@"Alpha",@"Beta",@"Gamma",@"X",nil];

NSString*string=@"gamma";


[aSetenumerateObjectsUsingBlock:^(idobj,BOOL*stop){

if([objlocalizedCaseInsensitiveCompare:string]==NSOrderedSame){

*stop=YES;

found=YES;

}

}];


//Atthispoint,found==YES


CopyingBlocks

Typically,youshouldn’tneedtocopy(orretain)ablock.Youonlyneedtomakeacopywhenyouexpecttheblocktobeusedafterdestructionofthescopewithinwhichitwasdeclared.Copyingmovesablock
totheheap.
YoucancopyandreleaseblocksusingCfunctions:

Block_copy();

Block_release();

Toavoidamemoryleak,youmustalwaysbalancea 
Block_copy()
 with 
Block_release()
.


PatternstoAvoid

Ablockliteral(thatis, 
^{...}
)istheaddressofa stack-local datastructurethatrepresents
theblock. Thescopeofthestack-localdatastructureisthereforetheenclosingcompoundstatement,soyoushould avoid thepatternsshowninthefollowingexamples:

voiddontDoThis(){

void(^blockArray[3])(void); //anarrayof3blockreferences


for(inti=0;i<3;++i){

blockArray[i]=^{printf("hello,%d\n",i);};

//WRONG:Theblockliteralscopeisthe"for"loop.

}

}


voiddontDoThisEither(){

void(^block)(void);


inti=random():

if(i>1000){

block=^{printf("gotiat:%d\n",i);};

//WRONG:Theblockliteralscopeisthe"then"clause.

}

//...

}


Debugging

Youcansetbreakpointsandsinglestepintoblocks.YoucaninvokeablockfromwithinaGDBsessionusing 
invoke-block
,
asillustratedinthisexample:

$invoke-blockmyBlock1020

IfyouwanttopassinaCstring,youmustquoteit.Forexample,topass 
thisstring
 intothe 
doSomethingWithString
 block,
youwouldwritethefollowing:

$invoke-blockdoSomethingWithString"\"thisstring\""

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: