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

以下Objective-C代码是否会产生强引用循环?回调引用self存疑

你的代码会不会产生强引用循环?

答案是:不会形成永久的强引用循环,但直接在block里用self还是有潜在问题,咱们来一步步拆解:

为什么不会形成循环引用?

强引用循环的核心是「两个或多个对象互相持有强引用,形成ARC无法自动释放的引用环」。咱们梳理下当前的引用关系:

  • UIImagePickerController(代码里的picker)会强引用传入的completion block;
  • 你的completion block里直接写了self,所以block会强引用当前的视图控制器;
  • 关键是:self并没有强引用这个picker——picker是方法参数,你没在self里用强引用属性持有它,而且UIKit内部的presentingViewController是弱引用(专门用来避免循环)。

当dismiss动画完成后,UIKit会释放picker,picker随之释放它持有的block,block也会释放对self的强引用,整个引用链直接断开,ARC能正常回收这些对象,不会形成永久循环。

那直接用self有什么问题?

虽然不会触发循环引用,但直接强引用self可能带来两个麻烦:

  • 延长self的生命周期:如果用户已经把当前页面pop掉,self本来该被释放,但因为block持有强引用,self会被保留到block执行完毕,造成不必要的资源浪费;
  • 潜在逻辑错误:如果self的状态(比如profileViewModel)在block执行前已经失效,继续执行代码可能引发异常或不符合预期的行为。

推荐的正确写法

用「弱引用+强引用」的组合,既从根源避免循环引用,又保证block执行期间self不会被意外释放:

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
    // 先创建self的弱引用
    __weak typeof(self) weakSelf = self;
    [picker dismissViewControllerAnimated:YES completion:^{
        // 在block内部转为强引用,避免self执行过程中被释放
        __strong typeof(weakSelf) strongSelf = weakSelf;
        if (!strongSelf) return; // self已经释放的话直接退出
        
        UIImage *image = [strongSelf cropImageWithInfo:info];
        if (currentScreen == CurrentScreenApartment) {
            [strongSelf.profileViewModel.apartmentPhotos addObject:[RuntimePhoto runtimePhotoWithImage:image]];
        } else {
            // 你的其他逻辑
        }
    }];
}

这种写法的好处:

  1. 弱引用weakSelf不会让block持有self的强引用,彻底杜绝循环引用可能;
  2. 内部转强引用strongSelf,保证代码执行期间self的稳定性,避免野指针;
  3. 先判断strongSelf是否为空,确保后续代码只在self有效时执行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:56:49