First look at this article juejin.cn/post/684490…

The basic definition

 <# # > return value type (^ < # # blockName alias >) (< # # parameterTypes preach and >) = ^ (< # parameters# >) {
        <#statements#>}; // There is no return value, there is a pass argument void(^testBlock)(NSString* ) = ^(NSString*name) {
        NSLog(@"% @",name);
    };
    testBlock(@"I mean."); NSInteger(^numtotal)(NSInteger,NSInteger) = ^(NSInteger a,NSInteger b) {return a + b ;
    };
    NSLog(@"Sum of two numbers: %ld", numtotal (1, 2));Copy the code

Blocks are also oc objects in nature

 handleNum block1 = ^(NSInteger num){
//        NSLog(@"%ld",a);
    };
    NSLog(@"% @",[block1 class]);
    NSLog(@"% @",[[block1 class] superclass]);
    NSLog(@"% @",[[[block1 class] superclass] superclass]);
    NSLog(@"% @",[[[[block1 class] superclass] superclass] superclass]);
Copy the code

Print the result

Capturing external values

NSInteger age = 12; void(^testBlock)(NSString* ) = ^(NSString*name) {
        NSLog(@"%@--%ld",name,age);
    };
    
    NSLog(@"%ld",age);
    age = 433;
    NSLog(@"%ld",age);
    testBlock(@"I mean.");
Copy the code

__block NSInteger age = 12; Or use the static keyword, the global variable void(^testBlock)(NSString* ) = ^(NSString*name) {
        age = 3;
        NSLog(@"%@--%ld",name,age);
    };
    
    NSLog(@"%ld",age);
    age = 433;
    NSLog(@"%ld",age);
    testBlock(@"I mean.");
    NSLog(@"%ld",age);

Copy the code

The print result is as follows

  Person* age = [Person new];
    age.name= @"12";
    void(^testBlock)(NSString* ) = ^(NSString*name) {
        NSLog(@"% @, % @",name,age);
    };
    
    NSLog(@"% @",age);
    [age setName:@"33333"];
    NSLog(@"% @",age);
    testBlock(@"I mean.");
Copy the code

  Person* age = [Person new];
    age.name= @"12";
    void(^testBlock)(NSString* ) = ^(NSString*name) {
         [age setName:@"dddd"];
        NSLog(@"% @, % @",name,age);
    };
    
    NSLog(@"% @",age);
    [age setName:@"33333"];
    NSLog(@"% @",age);
    testBlock(@"I mean.");
Copy the code

And that’s fine, because it operates on the object to which the pointer points, it doesn’t change the point of the pointer.

In real development, this is rarely used as above, and is more often passed as a parameter.

typedef void(^handleNum)(NSInteger);

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.title = @"aaavc";
    self.view.backgroundColor = [UIColor lightGrayColor];
 
    handleNum ha =  ^(NSInteger num){
        NSLog(@"%ld",num); }; // The second parameter is block [self numbOperation:@[@2,@4,@5,@6] andhanle:^(NSInteger num) {NSLog(@"%ld",num);
    }];
}

- (void)numbOperation:(NSArray*)array andhanle:(handleNum)block
{
    NSUInteger count = [array count];
    for (NSUInteger i = 0; i < count; i++) {
        block([array[i] integerValue]); }}Copy the code

The most common problem with blocks is the problem of circular references. Circular references can also occur in a delegate or NSTimer. As mentioned earlier, if a block accesses an external variable, it captures the value. A block is also an object, it has an ISA pointer, it also has a reference count. If an object holds a block and the object is captured inside the block, then a circular reference is generated.

{
    NSString* _name;
}

 __weak AViewController* weakVC = self;
    self.nameBlock = ^{
        __strong AViewController* vc = weakVC;
        vc->_name ;
    };
Copy the code

Note: self.property calls the settergetter method, vc->_name is the only method to access a member variable, not the setter method.

When will __strong be used?

If we use a weak pointer, the object will be released. If we add, the object will crash. To ensure that the object will not be released during the block execution, we can initialize a strong pointer inside the block. The validation described in this article is correct. Note that in arc, you cannot call retainCount directly, you need to use bridge

    NSLog(@"after block retainCount:%zd", CFGetRetainCount((__bridge CFTypeRef)obj));

Copy the code

www.jianshu.com/p/fe772a353…

Why does block use copy?

NSGlobalBlock: a global static block that has no access to external variables. Your block is of this type (i.e. your block does not call any other external variables). Blocks on the stack, not decorated with copy and access to external variables, your block type is that, It will be destroyed at the end of the function call (in MRC). 3 NSMallocBlock Block stored in the heap. This type of block blCOK is a block that is modified with copy and it will be destroyed when the object is destroyed, so as long as the object is not destroyed, we can call the block in the heap.

By default, blocks are archived on the stack, so blocks are destroyed at the end of a function call, null-pointer exceptions are raised at the end of the call, and if you use copy, it can be stored in the heap, and its life will end when the object is destroyed. We can call blocks in the heap as long as the object is not destroyed.

A block cannot modify an object pointer. Why? That’s the same reason for int A. Let’s look at this picture

If you change p inside a block, you cannot change the pointer to p outside the block.

What is the memory result of the block?

Answer: www.cnblogs.com/lybSkill/p/…

Recommended reading: www.jianshu.com/p/4e79e9a0d…