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

使用ALAssetsLibrary的writeVideoAtPathToSavedPhotosAlbum时App随机崩溃求助

解决视频保存时的Bad Access崩溃问题

这个bad access崩溃大概率是因为异步操作中对象的生命周期管理不当,结合你的代码,我整理了几个核心的排查和解决方向:

1. 核心原因:ALAssetsLibrary实例被提前释放

writeVideoAtPathToSavedPhotosAlbum是异步方法,它的completionBlock会在操作完成后才触发。而你代码中的ALAssetsLibrary *library是局部变量,在ARC环境下,当前方法执行完毕后这个实例就会被自动释放。当后续block回调触发时,访问已经被释放的library对象就会导致野指针错误(bad access)。

修复方案:延长library的生命周期

可以通过两种方式解决:

  • 将library声明为当前类的强引用属性,确保它在block执行完成前不会被释放;
  • 用__strong修饰局部变量,强制延长其生命周期:
if([[NSFileManager defaultManager] fileExistsAtPath:videoPath]) {
    // 用__strong修饰,避免实例被提前释放
    __strong ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
    [library writeVideoAtPathToSavedPhotosAlbum:[NSURL fileURLWithPath:videoPath] completionBlock:^(NSURL *assetURL, NSError *error) {
        if (error) {
            NSLog(@"视频保存失败:%@", error.localizedDescription);
        }
        // 操作完成后可以清理缓存文件
        [[NSFileManager defaultManager] removeItemAtPath:videoPath error:nil];
    }];
}

2. 补充:增加边界检查避免潜在崩溃

你的代码还有几个可以优化的边界点,虽然不是这次崩溃的直接原因,但能避免其他潜在问题:

  • 检查arrjid的数组长度:如果jid为空或者不包含@符号,componentsSeparatedByString会返回包含原字符串的数组,但最好加上判断避免意外:
    NSString *jidPrefix = arrjid.count > 0 ? arrjid[0] : @"unknown_user";
    
  • 检查缓存目录是否存在:NSSearchPathForDirectoriesInDomains理论上不会返回空数组,但加上判断更稳妥:
    NSArray *cacheDirs = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
    if (cacheDirs.count == 0) {
        NSLog(@"无法获取缓存目录");
        return;
    }
    
  • 检查视频数据写入是否成功:writeToFile会返回BOOL值,建议判断写入结果再执行后续操作:
    BOOL writeSuccess = [videoData writeToFile:videoPath atomically:YES];
    if (!writeSuccess) {
        NSLog(@"视频数据写入失败");
        return;
    }
    

3. 长远方案:替换为更稳定的Photos框架

ALAssetsLibrary在iOS 9之后已经被官方弃用,推荐使用Photos框架来处理相册操作,不仅更稳定,还能获得更好的兼容性:

// 记得导入Photos框架
#import <Photos/Photos.h>

// ... 前面的路径处理代码 ...

if([[NSFileManager defaultManager] fileExistsAtPath:videoPath]) {
    [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
        // 创建视频保存请求
        PHAssetChangeRequest *changeRequest = [PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:[NSURL fileURLWithPath:videoPath]];
    } completionHandler:^(BOOL success, NSError *error) {
        dispatch_async(dispatch_get_main_queue(), ^{
            if (success) {
                NSLog(@"视频保存到相册成功");
            } else {
                NSLog(@"视频保存失败:%@", error.localizedDescription);
            }
            // 清理缓存文件
            [[NSFileManager defaultManager] removeItemAtPath:videoPath error:nil];
        });
    }];
}

额外提醒:检查相册权限

确保你的App已经申请了相册访问权限,在Info.plist中添加对应的权限描述(NSPhotoLibraryAddUsageDescription和NSPhotoLibraryUsageDescription),虽然权限问题不会直接导致bad access,但会引发保存失败的错误。

内容的提问来源于stack exchange,提问作者shraddha k vaishanani

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:47:08