Introduction to the

A Block is an object that encapsulates a function and its execution context. You can save a piece of code and call it when you need it.

The statement

The format is: return value type (^Block name)(argument list); Such as:

Void (^aBlock)(void); // Return int(^aBlock)(void); // Return NSString* (^aBlock)(NSString * x, int y); // Returns NSString* (^aBlock)(void);Copy the code
  • Block property, use copy modifier, preferably not strong.
@property(nonatomic,copy)NSString* (^ablock)(void);
Copy the code
  • User-defined Block type
typedef void (^Block)(void);
typedef int (^MyBlock)(int a, int b);
typedef void(^ConfirmBlock)(BOOL isOK);
typedef NSString *(^AlertBlock)(NSInteger alertTag);
Copy the code

The assignment

The assignment format is: Block variable name = ^ Return type (argument list){function body}; Such as:

Self. aBlock = ^{NSLog(@"... ..." ); }; // Return self.ablock = ^NSString *{NSLog(@"dd"); return @"dd"; }; // Return self.ablock = ^NSString *(int a) {return @"vv"; }; // Return self.aBlock = ^(NSString *x, int y){NSLog(@" MMM "); };Copy the code

Blocks are called by the object of their class and indicate what to do. So a block contains a piece of code, which means that you’re going to do something, and you’re going to do something like assign a value to a property, but you’re going to assign a piece of code to a block.

call

Called by the class object to which it belongs. Similar method calls are as follows:

// Return self.ablock(); NSString *result = self.ablock(2);Copy the code

application

When dealing with asynchronous problems, such as HTTP requests, it’s a bit like a javascript callback that updates the main thread when it gets a reply, rather than using the main thread, which is much nicer than Delegate logic. Or when you want to return multiple values and don’t bother to create a class.

#####1. Pass data (pass data out, reverse)

  • In its own.h, declare a block property with arguments.
@interface PDMineVC : PDViewController

@property(nonatomic,copy)void (^rebackBlock)(NSString *flag);

@end
Copy the code
  • In.m, we call block.
// call self.rebackBlock(@"425"); // call self.rebackBlock(@"425");Copy the code
  • In the outside world

Class objects define their own block properties.

PDMineVC *vc = [[PDMineVC alloc] init];
vc.rebackBlock = ^(NSString *flag) {
    NSLog(@"--%@",flag);
};
[self.navigationController pushViewController:vc animated:YES];
Copy the code
2. Capture variables

There are two ways: value pass and pointer pass

  • The case of value passing

Local variables are modified after a Block is declared but before a Block is called. After a Block is called, the value of the local variable does not change.

int temp = 100; / / statement Block void (^ myBlock) () = ^ {NSLog (@ "global = % d", temp); }; temp = 101; // Change the value of the variable // call Block myBlock(); // "temp = 100"Copy the code

Explanation: When a Block is declared, only the value of the variable is stored in the Block code Block, so when a Block is called, the original value of the variable is still printed.

A reference to a variable outside a block, which is accessed by copying its value into its data structure by default.

  • The case of pointer passing

In the former case, you simply decorate the variable with __block, and whenever the value of the variable changes, the value changes with it.

__block int temp = 100; 
Copy the code

Explanation: For external variable references decorated with __block, block copies the reference address.

Note:

Local variables cannot be modified in blocks; Global variables, static variables, and Block values are also changed.

#####3. Save a piece of code that defines a Block in one class and calls a Block in another.

#####4. Block as a parameter of a function. Block is used as a parameter of a method. example

Method declaration +(void)checkNetworkStatusOn:(void (^)(NSString * status))CallBack; +(void)checkNetworkStatusOn (void (^)(NSString * status))CallBack{//... // blcok call, passing information CallBack? CallBack(@" network is disconnected ") : nil; } method call and declare Block [self checkNetworkStatusOn:^(NSString *status) {NSLog(@"---->%@",status);}];Copy the code
Typedef void(^selectedHandler)(NSUInteger index,NSString *title); // declare the method, Block as argument - (instancetype)initWithFrame:(CGRect)frame titles:(NSArray *)titles selectedHandler:(selectedHandler)handler;  - (instancetype)initWithFrame:(CGRect)frame titles:(NSArray *)titles selectedHandler:(selectedHandler)handler { if ( [super initWithFrame:frame]) { self.ablock = handler ; } return self; }Copy the code
5. Block as the return value of a function (rarely used)
Copy the code

Block memory Management

If a Block is copied once, its memory is moved to the heap, requiring the developer to manage its memory.

When a Block is stored in the heap, if an external object is referenced in the Block, a retain operation is performed on that object. Even after the Block itself calls release, the object is not released, causing a memory leak.

Person *pObject = [[Person alloc] init]; void(^myBlock)() = ^{ NSLog(@"------%@", pObject); }; myBlock(); Block_copy(myBlock); // copy operation //... Block_release(myBlock); [pObject release]; // --> The Person object cannot be released properly here because it was retained in the Block.Copy the code

To not do a retain operation on the referenced object, you can decorate the object with __block

__block Person *pObject = [[Person alloc] init];
Copy the code

Block loop reference

If an object has a Block property inside it and the object is accessed from within the Block, a circular reference is made. Solution:

  • __blockmodified

Prefacing an object with a __block modifier to prevent a Block from performing a retain operation on the object. __block Person *p = [[Person alloc] init];

  • A weak pointer

Create a new weak pointer to the object and use the weak pointer in a Block so that the Block does not cause a circular reference.

__weak typeof(Person) weakP = p;

void(^myBlock)() = ^{
    NSLog(@"------%@", weakP);
};

Copy the code

This solves the problem of circular references, but it is also prone to another problem: because the Block refers to a Person object by weak reference, it is possible that the Person object will be freed before the Block is called. So we need to define a strong pointer inside the Block to point to the Person object.

__weak typeof(Person) wp = p;
    aBlock = ^(NSString *flag) {
        
        __strong typeof(Person) sp = wp;
        
        NSLog(@"%@", sp);
    };
Copy the code

Supplement:

By default, the Block’s memory is stored in the heap,ARC takes care of the memory management automatically, and programmers just need to avoid circular references. Variables defined inside a Block are automatically released at the end of scope. The Block does not have a strong reference to them, and loop references are avoided in ARC. Strong references to external variables by the Block alone do not leak memory.

The relevant data

www.jianshu.com/p/14efa33b3… * www.jianshu.com/p/649fca982… www.jianshu.com/p/45557fbef… www.jianshu.com/p/c389afedb… *