SoFunction
Updated on 2025-04-12

Definition and use of block in iOS

concept

Code block block is an extension to C language introduced by Apple in iOS4, which is used to implement the characteristics of anonymous functions. Block is a special data type that can define variables, as parameters, and as return values ​​normally. In particular, block can also save a piece of code and call it when needed. At present, block has been widely used in iOS development and is often used in GCD, animation, sorting and various callbacks.

block: Let's call code block, it's similar to a method. Each method is called from the hard disk to the memory and then executed, and disappears after execution. Therefore, the memory of the method does not need to be managed, that is, the method is in the stack area of ​​the memory. Therefore, block is not like the class object in OC (in the heap area), it is also in the stack area. If we use block as an object's attribute, we will use the keyword copy to modify it, because it is in the stack area, and we cannot control its demise. When we use copy to modify it, the system will copy the block implementation to the heap area, so that our corresponding attributes will have ownership of the block. This ensures that the block code block will not die out in advance.

Definition and use

Block variable declaration

The declaration format of block variable: return value type (^block name) (parameter list);

block Variable declaration format:Return value type(^blockname)(Parameter list);
 //Declare a block with no return value and two parameters void(^block1)(NSString *a,NSString *b);
 //Omitted writing void(^block2)(NSString *,NSString *);

Assignment of block variable

 // Assignment of block variable //block variable name = ^(parameter list){function body}; block1 = ^(NSString *x,NSString *y){
 NSLog(@"%@--%@",x,y);
 };
 block1(@"123123",@"QWEQWEQWE");

Assign values ​​while declaring block variables

 //Assign block variables at the same time int(^block3)(int) = ^(int a){
 return a*3;
 };
 NSLog(@"%d",block3(3));

Use typedef to define block types

In the actual process of using block, we may need to repeatedly declare multiple Block variables with the same return value and the same parameter list. It will be very cumbersome if we always write a long string of code to declare variables repeatedly, so we can use typedef to define the Block type

#pragma mark Use typedef to define block types //Define a block with no return value type and no parameter list typedef void (^Block4)();
 Block4 block4 = ^(){
  NSLog(@"i am block4");
 };
 block4();

block as function parameter

#pragma mark block as function parameter int(^block5)(int,int) = ^(int a,int b){
  return a+b;
 };
 [self useBlock5:block5];
 
 //Simplify writing //typedef int (^Block6)(int,int); (global statement) Block6 block6 = ^(int a,int b){
  return a+b;
 };
 [self useBlock6:block6];
 
 
- (void)useBlock5:(int(^)(int,int))block5 {
 NSLog(@"block5:%d",block5(3,5));
}
- (void)useBlock6:(Block6 )block6{
 NSLog(@"block6:%d",block6(4,5));
}

Access local variables within block

  • Local variables can be accessed in Block
  • After declaring the Block and before calling the Block, the local variable value is the old value before the modification when calling the Block.
  • Local variables cannot be modified directly in Block
#pragma mark block -------------------------------------------------------------------------------------------------------------------------- // Local variables cannot be modified directly in block int value1 = 100;
 void (^block7)(void) = ^(){
   NSLog(@"value1:%d",value1);
 };
 value1 = 200;
 block7();//Output100 
  • Use underscore block to modify the local variable before the local variable. After declaring the block and calling the block, the local variable value is the new value after the modification.
  • Use underscore block to modify the local variable before local variables. Local variables can be directly modified in the Block
#pragma mark block -------------------------------------------------------------------------------------------------------------------------- // Local variables cannot be modified directly in block //Use __block to modify local variables before local variables. Local variables can be directly modified in Block __block int value1 = 100;
 void (^block7)(void) = ^(){
   value1++;
  NSLog(@"value1:%d",value1);
 };
 value1 = 200;
 block7();//Output100 __block 修饰之后Output200

Access global variables within block

After declaring the Block and before calling the Block, the global variable is modified. When calling the Block, the global variable value is the new value after the modification

#pragma mark --------------------------------------------------------------------------------------------------------------------------- //Global variables can be accessed in Block value2 = 100;
 void(^block8)(void) = ^(){
  //The global variable can be modified directly in the Block  self->value2++;
  NSLog(@"value2:%d",self->value2);
 };
 value2 = 200;
 block8();

Accessing static variables within block

#pragma mark --------------------------------------------------------------------------------------------------------------------------- static int value3 = 100;
 void(^block9)(void) = ^(){
  value3++;//Can static variables be modified directly in Block  NSLog(@"value3:%d",value3);
 };
 //Modify the static variable after declaring the Block and before calling the Block. When calling the Block, the static variable value is the new value after the modification. value3 = 200;
 block9();

Circular reference problems caused by block

If there is a Block property inside the object and the object is accessed inside the block, it will cause a circular reference

Situation 1

@interface Person : NSObject

@property (nonatomic, copy) void(^myBlock)();

@end


@implementation Person

- (void)dealloc
{
 NSLog(@"Person dealloc");
}

@end


Person *p = [[Person alloc] init];
  
 = ^{
 NSLog(@"------%@", p);
};
();
  
// becausemyBlockAsPersonProperties of,usecopyModifier modification(This will ensureBlockInside the pile,so as not toBlockRelease by the system in the stack),soBlockWill be correctPersonA strong reference to the object,Causes the circular reference to be unreleased

Situation 2

@interface Person : NSObject

@property (nonatomic, copy) void(^myBlock)();

- (void)resetBlock;

@end


@implementation Person

- (void)resetBlock
{
  = ^{
  NSLog(@"------%@", self);
 };
}

- (void)dealloc
{
 NSLog(@"Person dealloc");
}

@end


Person *p = [[Person alloc] init];
[p resetBlock];

// PersonThe object cannot be released normally here,existresetBlockMethod implementation,BlockInternal pairselfA strong quote was made,Causes the circular reference to be unreleased

The solution to circular reference is to use a weak reference pointer to point to the object, and then use the weak reference pointer inside the Block to operate, which avoids Block's strong reference to the object.

Situation 1

@interface Person : NSObject

@property (nonatomic, copy) void(^myBlock)();

@end


@implementation Person

- (void)dealloc
{
 NSLog(@"Person dealloc");
}

@end


Person *p = [[Person alloc] init];
__weak typeof(p) weakP = p;

 = ^{
 NSLog(@"------%@", weakP);
};
();
  
// PersonThe object can be released normally here

Situation 2

@interface Person : NSObject

@property (nonatomic, copy) void(^myBlock)();

- (void)resetBlock;

@end


@implementation Person

- (void)resetBlock
{
 // For the sake of being more general, you can use __weak typeof(self) weakP = self; __weak Person *weakP = self;
  = ^{
  NSLog(@"------%@", weakP);
 };
}

- (void)dealloc
{
 NSLog(@"Person dealloc");
}

@end


Person *p = [[Person alloc] init];
[p resetBlock];

// PersonThe object can be released normally here

Summarize

The above is the entire content of this article. I hope that the content of this article has certain reference value for your study or work. Thank you for your support.