First, the simplest block

1, the simplest block structure

^{
    NSLog(@"this is a block");
    NSLog(@"this is a block");
    NSLog(@"this is a block");
};
Copy the code

2. Block calls

^{
    NSLog(@"this is a block");
    NSLog(@"this is a block");
    NSLog(@"this is a block"); } ();Copy the code
void (^block)(void) = ^{
    NSLog(@"this is a block");
    NSLog(@"this is a block");
    NSLog(@"this is a block");
};
block();
Copy the code

2. The underlying structure of block

  • Use terminalcdtomain.mFile folder and execute the following command line
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m
Copy the code
  • The generatedmain.cppDrag the file into the project and open it to see the compiled versionmainDelta function, you can see thatblockDefinition and invocation of

  • inmain.cppThe following code can also be found in

  • You can seeblockThe underlying structure is__main_block_impl_0The structure of the body
  • blockThe code block is also wrapped into a function__main_block_func_0
  • __main_block_impl_0The first argument to__block_implThe structure is as follows

  • so__main_block_impl_0The structure can be viewed as follows, because the first member variable isisa, soblockThe essence is aOC object

  • Take a look atmainFunction will be createdblockObject to delete the cast type, you can see the following

  • To create __main_block_IMPL_0, we pass in two arguments, the first of which is the address of the __main_block_func_0 function that encapsulates the block code block, __main_block_desc_0(0, __main_block_IMPL_0)

  • Then look at the __main_block_IMPL_0 constructor

  • You can see__main_block_func_0The function address assigned to__block_implA member variable of a structureFuncPtr.blockIs assigned to the second member variableDesc

Summary: The essence of a block is an OC object that encapsulates a function call and its environment

  • blockThe call is made by findingimplIn theFuncPtrTo get to the__main_block_func_0The address of the function is then called and passed in at the same time__main_block_impl_0The address of the

  • The reason why we use it directly hereblock->FuncPtrRather thanblock->impl.FuncPtrBecause,implisstruct __main_block_impl_0The first member variable of, soimplThe address andblockHave the same address

  • So you can passblockPointer is used directlyFuncPtr

The underlying structure of a block with parameters

  • When you define a block, you can pass in parameters

  • Use terminalcdtomain.mFile folder and execute the following command line
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m
Copy the code
  • The generatedmain.cppDrag the file into the project and open it to see the compiled versionmainDelta function, you can see thatblockDefinition and invocation of

  • After deleting the type conversion, the code is called as followsblockWhen introduced into the10and20

4. Variable capture of block

  • There are three main types of variables in OC, namelyAuto, static, global variables, includingAuto and staticModification isA local variable
  • These three types of variables are captured differently by blocks when they are used

1. Auto variable capture (value capture)

  • In OC, the variables that we define, by default, areautoType, which is destroyed when it leaves scope
  • whenblockVariable capture is performed when external variables are used in

  • Use terminalcdtomain.mFile folder and execute the following command line
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m
Copy the code
  • The generatedmain.cppDrag the file into the project and open it, and you can see the compiled block
  • You can find__main_block_impl_0There is one more member variable in the structureagetheageIs based onmainIn the functionageGenerated member variables
  • __main_block_impl_0In theageandmainIn the functionageAre two independent variables

  • blockUsed when calledageis__main_block_impl_0Is a member variable instead ofmainIn the functionage

  • whileageIs the value ofblockPassed in when created

  • So in themainIn the delta function, if the delta function isblockModify the age value after definition in the callblockWhen,ageThe value of phi does not change

  • The underlying structure is as follows

2. Static variable capture (pointer capture)

  • There is code as follows to usestaticmodifiedagevariable

  • At the bottom of the__main_block_impl_0In theageType is a pointer typeint *

  • To the instructionsstaticA modified variable captures the address of the variable__main_block_impl_0In the
  • At this timemainFunction, call__main_block_impl_0Is passed to the constructor ofageThe address of the

  • inblockCall,__main_block_func_0The function also passesageAddress access ofageThe value of the

  • At this point, ifmainIn the functionblockSubsequent modifications to the definitionageThe value of, then inblockAccessed by address inageThat’s the modified value

  • The underlying call code is as follows

Use global variables in block (no capture)

  • At this timeblockThe underlying structure of,blockDid not captureage“, but directly use

Summary: If a global variable is used in a block, the global variable is not captured in the block. When a block is called, the global variable is used directly, so the value of the global variable changes, and the value used in the block changes accordingly

  • Modify theageValue in the callblockAs you can seeblockThe values printed in the

4. Block captures auto, static and global variables

Summary: In a block, if you use a local variable, that variable is captured. In a block, if you use a global variable, that variable is not captured, but used directly