Block technology collection
Ios-block variable interception
1. The Block definition
Int (^ sumOfNumbers)(int a, int b) = (int a, int b) {return a + b; }; int sum = sumOfNumbers(1, 2); NSLog(@"sum = %d", sum); 2021-05-01 11:04:05.920543+0800 BlockDemo[18351:6429226] sum = 3Copy the code
This code declares a block named sumOfNumbers to the left of the equals sign, preceded by the ^ sign indicating that the string following the name is the block name. The leftmost int represents the return value of the block, and the parentheses between them represent the argument list of the block, which receives two ints. The right side of the equal sign represents the definition of the block, where the return value can be omitted and the compiler automatically supplements the return value type based on the context. A list of arguments is concatenated with the ^ symbol, wrapped in parentheses, telling the compiler that this is a block, and then wrapping the block’s code with curly braces.
2. Block method
return_type
Represents returned objects/keywords, etc. (usuallyvoid
)blockName
saidblock
The name of thevar_type
Represents the type of the parametervarName
Parameter name
1. As a local variable
Copy the code
return_type (^blockName)(var_type) = ^return_type (var_type varName) {
// ...
};
blockName(var);
int(^ sumOfNumbers)(int a, int b) = ^(int a, int b) {
return a + b;
};
Copy the code
2. As an attribute
@property (copy) return_type (^blockName) (var_type);
@property (nonatomic, copy) void(^ didLoginSuccess)(NSString *username);
@property (nonatomic, copy) void(^ didLoginFailed)(void);
Copy the code
3. Define the method as a Block parameter
- (void)yourMethod:(return_type (^)(var_type))blockName;
- (void)sumOfA:(int)a B:(int)b sumBlock:(void(^)(int sum))sumBlock {
int sum = a + b;
sumBlock(sum);
}
- (void)login:(void(^)(void))completion {
completion();
}
Copy the code
4. Block is the argument
The use of blocks as arguments is common in various frameworks, such as when wrapping a class, when the outside world decides what to do and when to call its own class.
[someObject doSomethingWithBlock: ^return_type (var_type varName)
{
//...
}];
Copy the code
Take customizing a simple tool class CalculatorManager as an example:
// // CalculatorManger.h // BlockDemo // // Created by Ternence on 2021/5/1. // #import <Foundation/Foundation.h> @interface CalculatorManger: NSObject @property (nonatomic, assign) int result; + (instancetype)sharedManager; //block is defined in the same format as other types, which are (type) variable names and look a bit confusing - (void)calculate:(int(^)(int))calculateBlock; @endCopy the code
// // CalculatorManger.m // BlockDemo // // Created by Ternence on 2021/5/1. // #import "CalculatorManger.h" static int defaultHeight = 100; static CalculatorManger * instance = nil; @implementation CalculatorManger + (instancetype)allocWithZone:(struct _NSZone *)zone { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ if (instance == nil) { instance = [super allocWithZone:zone]; }}); return instance;; } + (instancetype)sharedManager { return [[self alloc] init]; } // the method defines a block datatype argument (return int, Calculate :(void)calculate:(int (^)(int))calculateBlock {//calculateBlock accepts code blocks passed in, _result = calculateBlock(defaultHeight); } @endCopy the code
External controller call
CalculatorManger *manager = [CalculatorManger sharedManager];
[manager calculate:^int(int i) {
NSLog(@"=======i : %d", i);
for (int j = 0; j < 100; j ++) {
i++;
}
return i;
}];
NSLog(@"=====result: %d", manager.result);
Copy the code
It can be seen that the calculation method of CalculcatorManager of tool class calculateBlock calculate:^int(int)calculateBlock is left to external controller callers to decide. It’s a bit convoluted, but it’s easy to understand once you know the format of a block as an argument. If you were confused about the use of this type, hopefully this little example will help you 🙂
When a Block is implemented, such as the local variable and argument above, the right side of the equal sign is an anonymous Block, which has no blockName:
^return_type (var_type varName)
{
//...
};
Copy the code
6. typedef Block
Use typedef to simplify Block declarations
typedef return_type (^BlockTypeName)(var_type);
typedef void (^didQuitAcountBlock)(void);
Copy the code
use
BlockTypeName aBlock = ^return_type (var_type) {
//...
}
didQuitAcountBlock quitBlock = ^void(void) {
NSLog(@"did quit acount");
};
quitBlock();
Copy the code
7. An inline Block
This form is not commonly used. Anonymous blocks are called immediately after they are declared. Inline blocks can be used to Block code, improving readability
^return_type (var_type varName) { //... }(var); ^void() {NSLog(@" called after inline Block declaration "); } ();Copy the code
8. Call Block recursively
A Block calls itself internally, and recursive calls are the basis for many algorithms, especially if loop termination conditions cannot be predicted in advance. Note that since blocks refer to themselves internally, __block must be used here to avoid the retention ring problem.
__block return_type (^blockName)(var_type) = [^return_type (var_type varName)
{
if (returnCondition)
{
blockName = nil;
return;
}
// ...
blockName(varName);
} copy];
blockName(varValue);
Copy the code
The instance
__block int i = 5;
__block void (^ dismisssController)(void) = [^void(void) {
if (i == 0) {
dismisssController = nil;
return;
}
NSLog(@"recursionBlock i = %d", i);
i --;
dismisssController();
} copy];
dismisssController();
Copy the code
######8. Block is returned
- (return_type(^)(var_type))methodName
{
// ...
}
Copy the code
3. An example of Block parameter transmission
.h
@interface SecondViewController : UIViewController
@property (nonatomic, copy) void(^ didLoginSuccess)(NSString *username);
@property (nonatomic, copy) void(^ didLoginFailed)(void);
@end
Copy the code
.m
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ if (self.didLoginSuccess) { Self. DidLoginSuccess (@" code code for the ponies "); } if (self.didLoginFailed) { self.didLoginFailed(); }}Copy the code
Call block,
SecondViewController *vc = [[SecondViewController alloc] init];
[self.navigationController pushViewController:vc animated:true];
vc.didLoginSuccess = ^(NSString * _Nonnull username) {
NSLog(@"congratulations %@! welcome to objc world", username);
};
vc.didLoginFailed = ^{
NSLog(@"login failed");
};
Copy the code