You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Objective-C中能否在将Block传入方法后再进行定义?

嘿,这个问题我之前在项目里踩过坑!你现在的写法之所以失效,核心原因是你传递的是Block变量的当前值(nil),而不是变量本身的引用——后续给变量赋值并不会改变之前已经传进去的那个nil值,方法里拿到的始终是最初的空指针。

问题根源拆解

你当前的代码执行顺序逻辑是:

  1. 声明Block变量doStuffBlock,默认值为nil
  2. 将这个nil值传递给prepareToDoStuffWithCompletion:方法
  3. 后续给doStuffBlock赋值,但此时方法内部保存的还是之前传入的nil,两者完全没有关联

下面给你两种可行的解决方案,你可以根据代码场景选择:

方案1:传递Block的指针(原生C指针思路)

修改方法的参数类型,让它接受一个指向Block的指针,这样后续对Block变量的赋值就能被方法内部感知到。

首先调整方法的声明:

- (void)prepareToDoStuffWithCompletion:(void(^__autoreleasing *)(void))completionPtr;

调用时传递Block变量的地址:

// 声明Block变量
void (^doStuffBlock)(void);
// 传入Block的指针(注意&符号)
[self prepareToDoStuffWithCompletion:&doStuffBlock];
// 后续定义Block
doStuffBlock = ^void() {
    NSLog(@"执行Block内的操作");
};

在方法内部,需要通过指针调用Block(记得先判空避免崩溃):

- (void)prepareToDoStuffWithCompletion:(void(^__autoreleasing *)(void))completionPtr {
    // 模拟异步执行场景,比如延迟1秒调用Block
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        if (*completionPtr) { // 先判断指针指向的Block是否为空
            (*completionPtr)(); // 通过指针调用Block
        }
    });
}

方案2:用容器类包裹Block(OC风格的间接方式)

如果不想修改原有方法的参数类型,可以用NSMutableDictionary或NSMutableArray这类容器包裹Block——因为容器是引用类型,传递的是内存地址,后续修改容器内的Block会被方法内部感知到。

示例代码:

// 用可变字典包裹Block,初始值用NSNull占位
NSMutableDictionary *blockWrapper = [@{@"completion": [NSNull null]} mutableCopy];
// 传入容器对象
[self prepareToDoStuffWithCompletionWrapper:blockWrapper];
// 后续给容器内的Block赋值
blockWrapper[@"completion"] = ^void() {
    NSLog(@"执行Block内的操作");
};

方法内部的实现:

- (void)prepareToDoStuffWithCompletionWrapper:(NSMutableDictionary *)wrapper {
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        void(^completion)(void) = wrapper[@"completion"];
        if (completion && ![completion isKindOfClass:[NSNull class]]) {
            completion();
        }
    });
}

额外注意事项

  • 如果是在异步场景下使用,要确保Block变量或容器对象不会被提前释放,必要时用__strong修饰符持有对象,避免野指针崩溃
  • 方案1更偏向底层C语言逻辑,执行效率更高;方案2更符合OC的编码习惯,代码可读性更好,你可以根据自己的项目需求选择

内容的提问来源于stack exchange,提问作者richy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 14:07:48