• iOS高级理论:Block的应用


    Block 是 Objective-C 和 Swift 中的一种语言特性,可以用来封装一段代码并在需要时执行。在 iOS 开发中,Block 被广泛应用于以下场景:

    一、异步任务处理

    Block 可以用于异步任务的处理,例如网络请求、文件读写等。通过在 Block 中定义任务和回调,可以简化异步代码的编写。

    // 异步网络请求示例
    [NSURLSession.sharedSession dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        if (error) {
            NSLog(@"Error: %@", error.localizedDescription);
        } else {
            // 处理网络请求结果
        }
    }];
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    二、动态回调

    Block 可以作为回调函数传递,用于在某个操作完成后执行特定的代码。这种方式常用于处理用户交互、动画效果等。

    // 动态回调示例
    [UIView animateWithDuration:0.3 animations:^{
        // 执行动画效果
    } completion:^(BOOL finished) {
        if (finished) {
            // 动画完成后执行的代码
        }
    }];
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    三、事件处理

    Block 可以用于处理用户事件,例如按钮点击事件、手势识别等。通过给控件设置 Block 回调,可以简化事件处理的逻辑。

    // 按钮点击事件处理示例
    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
    [button setTitle:@"Click Me" forState:UIControlStateNormal];
    [button addTarget:self action:@selector(buttonTapped) forControlEvents:UIControlEventTouchUpInside];
    
    // Block 回调处理按钮点击事件
    button.tapAction = ^{
        NSLog(@"Button tapped");
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    具体案例:

    场景:UIViewContoller有个UITableView并是它的代理,通过UITableView加载CellView。现在需要监听CellView中的某个按钮(可以通过tag值区分),并作出响应。

    // 激活事件 #pragma mark - 按钮点击事件 
    - (IBAction)btnClickedAction:(UIButton *)sender { 
            if (self.btnClickedBlock) {           
                    self.btnClickedBlock(sender);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    随后,在ViewController.m的适当位置(- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{…代理方法)中通过setter方法设置CellView的Block属性。Block写着当按钮被点击后要执行的逻辑。

    // 响应事件 
    cell.btnClickedBlock = ^(UIButton *sender) { 
            //标记消息已读 
            [weakSelf requestToReadedMessageWithTag:sender.tag]; 
            //刷新当前cell 
            [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    其实,即使Block不传递任何参数,也可以传递事件的。但这种情况,无法区分事件的激活方(cell里面的哪一个按钮?)。即:

    //按钮点击Block @property (nonatomic, copy) void (^btnClickedBlock)(void);
    
    • 1
    // 激活事件 #pragma mark - 按钮点击事件 
    - (IBAction)btnClickedAction:(UIButton *)sender { 
            if (self.btnClickedBlock) { 
                    self.btnClickedBlock();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    // 响应事件 
    cell.btnClickedBlock = ^{ 
            //标记消息已读 
            [weakSelf requestToReadedMessageWithTag:nil]; 
            //刷新当前cell 
            [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    四、数据传递

    Block 可以用于传递数据或者操作,例如在界面之间传值或者执行某些操作后返回结果。

    // 数据传递示例
    [self presentViewController:secondViewController animated:YES completion:^{
        secondViewController.completionBlock = ^(BOOL success) {
            if (success) {
                NSLog(@"Data transfer successful");
            }
        };
    }];
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    具体案例:

    场景:上面的响应事件,其实也是传递数据,只是它传递的对象是UIButton。如下所示,SubTableView是VC的一个属性和子视图。

    4.1 传递数值
    SubTableView.h
    
    @property (strong, nonatomic) void (^handleDidSelectedItem)(int indexPath);
    
    • 1
    • 2
    • 3
    SubTableView.m
    
    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    {
        [tableView deselectRowAtIndexPath:indexPath animated:YES];
        _handleDidSelectedItem ? _handleDidSelectedItem(indexPath) : NULL;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    VC.m
    
    [_subView setHandleDidSelectedItem:^(int indexPath) {
        [weakself handleLabelDidSearchTableSelectedItem:indexPath];
    }];
    
    - (void)handleLabelDidSearchTableSelectedItem:(int )indexPath { if (indexPath==0) {
            [[UIApplication sharedApplication] openURL:[NSURL URLWithString:[NSString stringWithFormat:@"telprompt:%@", self.searchNullView.telLabel.text]]];
        }else if (indexPath==1){
            [self.navigationController popViewControllerAnimated:YES];
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    4.2 传递对象

    例如HYBNetworking网络框架中请求成功时传递接口返回数据对象的Block:

    [HYBNetworking postWithUrl:kSearchProblem refreshCache:NO params:params success:^(id response) {          
          typeof(weakSelf) strongSelf = weakSelf; 
        //[KVNProgress dismiss]; NSString *stringData = [response mj_JSONString];
        stringData = [DES3Util decrypt:stringData]; NSLog(@"stirngData: %@", stringData);
           ...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    总的来说,iOS 中的 Block 是一种非常灵活和强大的工具,可以简化代码逻辑、实现回调机制、处理异步任务等。合理地使用 Block 可以提高代码的可读性和可维护性,同时也能更好地适应 iOS 开发中的各种需求。

  • 相关阅读:
    InstDisc 代码解读
    在STM32F407的BSP基础上将RT-Thread移植到STM32F303VCT6上
    Python 随机(random)模块的不可预测之美
    elementor系统要求
    Spring AOP基础&动态代理&基于JDK动态代理实现
    Spring Boot接口设计规范
    ppt怎么转换成word文档呢?
    PyCharm配置Jupyter
    如何判断一个英文单词中是否存在重复字母
    计算机组成原理笔记(王道考研) 第三章:存储系统
  • 原文地址:https://blog.csdn.net/u010545480/article/details/136284961