SoFunction
Updated on 2025-04-12

Detailed explanation of iOS (closure) block transmission value

During the development of iOSAPP, we will use many places where value is needed. There are also many ways to pass values, including: proxy value transmission, notification value transmission, KVC, KVO, block, singleton, etc. Among them, block is undoubtedly the best choice for big guys to pass on values, but it is necessary for beginners to understand and be able to use it. It is indeed a bit difficult to understand at first. I will introduce block in detail below.

First, I summarize the block formula:

  1. Declaration of step Return value type (name of ^block) (parameter list);
  2. Steps Implement the name of the block = ^(parameter list)(){};
  3. The name of the call block of step ();

Here is a simple block

// Statement  void(^blockName)(int num,NSString *string); 
//  accomplish  blockName = ^(int num,NSString *string) 
  { 
    NSLog(@"%d,%@",num,string); 
  }; 
// Call  blockName(520,@"phyone_"); 
} 

From this example, we can see that the code execution order of block is different from that of other code execution order. It first executes the declaration code and then executes the call code. Finally, the implementation code is executed. Therefore, we use the callback nature of block to achieve the effect of passing values. Of course, this is just a piece of code on a page. It just shows that it has the function of passing values. Let's try the reverse transmission of block between multiple pages. Since it is a reverse transmission of value, we create two ViewControllers (ViewController, Next_ViewController) First, the ViewController jumps to Next_ViewController and the value in it is reverse transmission to the ViewController.
The following is the code

in

- (void)viewDidLoad { 
  [super viewDidLoad]; 
   = [UIColor purpleColor]; 
 UILabel *lable = [[UILabel alloc]initWithFrame:CGRectMake(100, 200, 200, 100)]; 
   = [UIColor brownColor]; 
  [ addSubview:lable]; 
   
  UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap)]; 
  [ addGestureRecognizer:tap]; 
} 
- (void)tap 
{ 
  Next_ViewController *NVC = [[Next_ViewController alloc]init]; 
   = ^(NSString *content){ 
    NSLog(@"%@",content); 
    UIButton *button = [[UIButton alloc]initWithFrame:CGRectMake(100, 200, 100, 100)]; 
    [button setTitle:content forState:UIControlStateNormal]; 
     = [UIColor orangeColor]; 
    [ addSubview:button]; 
  }; 
  [self presentViewController:NVC animated:YES completion:nil]; 
} 

In Next_ViewController.h

//block is allocated in the stack using copy@property(nonatomic,copy) void(^block)(NSString *content); 

In Next_ViewController.m

<p style="margin-top: 0px; margin-bottom: 0px; font-family: Menlo;"><span style="font-size:12px;">{</span></p>
<p style="margin-top: 0px; margin-bottom: 0px; font-family: Menlo;"><span style="font-size:12px;">  void(^imageNameBlock_1)(NSString *imageName);</span></p>
<p style="margin-top: 0px; margin-bottom: 0px; font-family: Menlo;"><span style="font-size:12px;">  void(^lableBlock)(NSString *tontentText);</span></p>
<p style="margin-top: 0px; margin-bottom: 0px; font-family: Menlo;"><span style="font-size:12px;">}</span></p> 
- (void)viewDidLoad { 
  [super viewDidLoad]; 
   = [UIColor orangeColor]; 
  UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; 
   = CGRectMake(100, 200, 100, 50); 
  [button setTitle:@"123456" forState:UIControlStateNormal]; 
   = [UIColor redColor]; 
  [button addTarget:self action:@selector(buttonAction:) forControlEvents:UIControlEventTouchUpInside]; 
  [ addSubview:button]; 
} 
- (void)buttonAction:(UIButton *)sender 
{ 
// Click the button to return to the previous page and pass this value to the previous page through block.  (); 
  [self dismissViewControllerAnimated:nil completion:nil]; 
}

In addition: block has two more questions

1. How to change the value in the block

Use the above code to add the code in viewDidLoad

 1.Local variables 
 Define an image nameBlock 
 */ 
// Local variables   
  void(^imageNameBlock)(NSString *imageName); 
// If you want to modify the value in the Block, you need to add __block modification   
//  __block UIImage *image; 
  imageNameBlock = ^(NSString *imageName) 
  { 
    image = [UIImage imageNamed:imageName]; 
     = [UIColor colorWithPatternImage:image]; 
  }; 
  imageNameBlock(@""); 

Use of undeclared identifier 'image' error will appear. The reason is that we are trying to change the value in the block. The solution is to add __block modification (explanation comments)

__block UIImage *image;)

Recycle reference

Use the above code to add the code in viewDidLoad

// Global variables// block loop reference solution We use weak reference __block  __weak ViewController *VC = self; 
   
  __block UIImage *image = nil; 
  imageNameBlock_1 = ^(NSString *imageName) 
  { 
    image = [UIImage imageNamed:imageName]; 
     = [UIColor colorWithPatternImage:image]; 
  }; 
  UILabel *lable = [[UILabel alloc]initWithFrame:CGRectMake(100, 200, 200, 100)]; 
   = [UIColor brownColor]; 
  [ addSubview:lable]; 
   
  UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap)]; 
  [ addGestureRecognizer:tap]; 

Add two more methods

- (void)loadData 
{ 
  imageNameBlock_1(@""); 
} 
 
- (void)viewWillAppear:(BOOL)animated 
{ 
  [self loadData]; 
} 

When circular references appear, we use __weak to modify them, but we don’t understand the specific mechanism very well. I hope the expert will give me some advice and thank you for your support.