The simplest block

^{NSLog(@"this is a block! ); NSLog(@"this is a block!" ); NSLog(@"this is a block!" ); NSLog(@"this is a block!" ); }; Blocks do not run by default, encapsulating all code and executing when appropriateCopy the code
^{ NSLog(@"this is a block!" ); NSLog(@"this is a block!" ); NSLog(@"this is a block!" ); NSLog(@"this is a block!" ); } (); test(); Call plus () as a functionCopy the code
void (^block)(void) = ^{ NSLog(@"this is a block!" ); NSLog(@"this is a block!" ); NSLog(@"this is a block!" ); NSLog(@"this is a block!" ); }; block(); // Call is saved first because it is called at the appropriate timeCopy the code

The nature of the block

  • A block is also essentially an OC object with an ISA pointer inside it
  • A block is an OC object that encapsulates a function call and its environment
int age = 20; void (^block)(int, int) = ^(int a , int b){ NSLog(@"this is a block! -- %d", age); }; block(10, 10); Function call environment: - parameter int a, int b - external access value int age = 20; So the block has an age in its memoryCopy the code
  • Generate a CPP

  • The underlying structure of BLCOK

  • The structure of the first parameter

  • The equivalent of

So the conclusion is that the first argument to block is the *isa pointer which is an OC object and we also see that there’s an age in it

  • Function methods are defined here

  • At block definition time, the __main_block_IMPL_0 method is called and passed to FP, which is copied to FuncPtr, and the function address is stored

  • When a block is called, it takes the address out of the function and calls it

Conclusion A block is an OC object structure that encapsulates a function call and its environment

  • Block A complete underlying structure
struct __main_block_desc_0 { size_t reserved; size_t Block_size; // Block object memory size}; struct __block_impl { void *isa; int Flags; int Reserved; void *FuncPtr; // function address}; struct __main_block_impl_0 { struct __block_impl impl; struct __main_block_desc_0* Desc; int age; // External value}; int age = 20; void (^block)(int, int) = ^(int a , int b){ NSLog(@"this is a block! -- %d", age); NSLog(@"this is a block!" ); NSLog(@"this is a block!" ); NSLog(@"this is a block!" ); }; struct __main_block_impl_0 *blockStruct = (__bridge struct __main_block_impl_0 *)block; Block (10, 10);Copy the code

  • The underlying structure of a block is shown in figure 1

Block variable capture

  • To ensure that external variables can be accessed within a block, blocks have a variable capture mechanism

  • Auto is a deep copy of value transfer
  • Static is passing a shallow copy of a pointer

Auto variable capture

  • And since the nature of function calls is that by default there’s a local variable that passes self so it’s captured by the value of the block, the block captures self

The type of the block

  • Block’s inheritance relationship

  • There are three types of blocks, which you can see by calling the class method or isa pointer. They are all derived from the NSBlock type
    • NSGlobalBlock (_NSConcreteGlobalBlock)
    • NSStackBlock (_NSConcreteStackBlock)
    • NSMallocBlock (_NSConcreteMallocBlock)

  • No access to auto -> global access to static or global variables as long as no access to auto is globalBlock

  • Turn off the ARC

  • The auto variable -> StackBlock is accessed

  • StackBlock calls copy and becomes mallocBlock
  • StackBlock becomes mallocBlock because arc automatically calls copy for memory management
  • Block to summarize

  • Stackblocks are automatically destroyed when placed out of scope
  • In the following functions, the stack space is reclaimed after the function is called, and a problem occurs when the block is called again
  • So stackBlock->mallocBlock

  • StackBlock calls copy->mallockBlock to the heap space

  • Each type of block calls copy as shown below

Block of copy

  • In an ARC environment, the compiler automatically copies blocks on the stack to the heap as needed, such as the following

    • Block as a function return value

    • Assigns a block to a __strong pointer

    • Block is used as a Cocoa API method name containing a method parameter called usingBlock

    • Block as a method parameter of the GCD API

  • Recommended writing method of block attribute under MRC

    • @property (copy, nonatomic) void (^block)(void);
  • Recommended way to write block properties under ARC

    • @property (strong, nonatomic) void (^block)(void);
    • @property (copy, nonatomic) void (^block)(void);

The auto variable of object type

  • When the block internally accesses the auto variable of the object type
    • If the block is on the stack, there is no strong reference to the auto variable

    • If the block is copied to the heap

      • The copy function inside the block is called
      • Copy calls the _Block_object_assign function internally
      • The _Block_object_assign function performs operations based on the __strong, __weak, and __unsafe_unretained modifier of the auto variable, generating a retained or weak reference
    • If a block is removed from the heap

      • Dispose function inside the block is called
      • The _Block_object_dispose function is called internally
      • The _Block_object_dispose function automatically releases the referenced auto variable (release)

__weak problem resolved

  • When using clang to convert OC to C++ code, you may encounter the following problems

    • cannot create __weak reference in file using manual reference
  • Solution: Support ARC, specify runtime system versions, e.g

    • Xcrun-sdk iphoneOS clang-arch arm64-rewrite-fobjc-arc-fobjc-Runtime =ios-8.0.0 main.m

__block qualifier

  • __block can be used to solve the problem of not being able to modify the value of the auto variable inside a block
  • __block cannot modify global or static variables.
  • The compiler wraps the __block variable call function as an object

The essence of __block: there will be a pointer of type __Block_byref_age_0 in a block. This pointer is a structure, and then the forwarding of the structure finds its own memory and takes out the age inside. Forwarding stores its own memory address.

Block memory management

  • When a block is on the stack, there is no strong reference to a __block variable

  • When a block is copied to the heap

    • The copy function inside the block is called
    • Copy calls the _Block_object_assign function internally
    • The _Block_object_assign function forms a strong reference to the __block variable (retain)

  • When a block is removed from the heap
    • Dispose function inside the block is called
    • The _Block_object_dispose function is called internally
    • The _Block_object_dispose function automatically releases the referenced __block variable (release)

__forwarding pointer to __block

The auto and __block variables of the object type

  • When blocks are on the stack, there are no strong references to any of them

  • When blocks are copied to the heap, they are processed by the copy function

    • A __block variable (assuming the variable name is a)

      • _Block_object_assign((void*)&dst->a, (void*)src->a, 8/BLOCK_FIELD_IS_BYREF/);
    • The auto variable of the object type (assuming the variable name is p)

      • _Block_object_assign((void*)&dst->p, (void*)src->p, 3/BLOCK_FIELD_IS_OBJECT/);
  • When blocks are removed from the heap, they are always disposed with the dispose function

    • A __block variable (assuming the variable name is a)

      • _Block_object_dispose((void*)src->a, 8/BLOCK_FIELD_IS_BYREF/);
    • The auto variable of the object type (assuming the variable name is p)

      • _Block_object_dispose((void*)src->p, 3/BLOCK_FIELD_IS_OBJECT/);

The object type modified by __block

  • When a __block variable is on the stack, there is no strong reference to the object to which it points

  • When a __block variable is copied to the heap

    • The copy function inside the __block variable is called
    • Copy calls the _Block_object_assign function internally
    • The _Block_object_assign function performs operations based on the __strong, __weak, and __unsafe_unretained attributes of the specified object to retain or weak references

    (Note: this is limited to retain for ARC and not FOR MRC)

  • If the __block variable is removed from the heap
    • Dispose function inside the __block variable is called
    • The _Block_object_dispose function is called internally
    • The _Block_object_dispose function automatically releases the object it points to.

Circular reference problem

Solve the circular reference problem -ARC

  • __BLOCK has the disadvantage of leaking memory if not called.

Solve circular reference problem -MRC

expand