部分用户App随机崩溃求助:ALAssetsLibrary相关CoreData崩溃问题
分析与解决ALAssetsLibrary保存相册时的随机崩溃问题
看起来你的App在使用ALAssetsLibrary保存视频/照片到相册时出现了随机线程崩溃,从Crashlytics的栈信息来看,崩溃发生在+[ALAssetsLibrary _library]这个内部方法调用时,而且和CoreData的NSManagedObjectContext队列相关——这大概率是线程安全冲突导致的。
崩溃原因拆解
ALAssetsLibrary在iOS内部其实依赖了CoreData来管理相册资源,但它的线程模型和你自己App的CoreData上下文没有做好隔离:
- 如果你在
NSManagedObjectContext的私有队列(比如performBlock:/performAndWait:块里)调用了ALAssetsLibrary的保存方法,就会导致两个CoreData相关的队列互相干扰,触发偶发的崩溃。 - 因为线程冲突是时机依赖的,所以只会在部分设备/场景下随机出现,很难稳定复现。
具体解决方案
1. 立即修复:隔离ALAssetsLibrary的执行队列
把保存相册的代码从CoreData上下文队列中移出来,放到主线程或者独立的后台队列中执行,确保CoreData操作和ALAssetsLibrary操作不在同一个队列里:
// 错误写法:在CoreData上下文块里调用ALAssetsLibrary [yourManagedContext performBlock:^{ // 处理CoreData逻辑... ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; [library writeVideoAtPathToSavedPhotosAlbum:videoURL completionBlock:^(NSURL *assetURL, NSError *error) { // 回调处理 }]; }]; // 正确写法:移到主线程执行ALAssetsLibrary操作 dispatch_async(dispatch_get_main_queue(), ^{ ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; [library writeVideoAtPathToSavedPhotosAlbum:videoURL completionBlock:^(NSURL *assetURL, NSError *error) { // 如果需要更新CoreData,再回到上下文队列 [yourManagedContext performBlock:^{ // 这里处理CoreData更新 }]; }]; });
2. 长期方案:替换为Photos框架(推荐)
ALAssetsLibrary在iOS 9之后就被苹果废弃了,官方推荐使用PHPhotoLibrary,它的线程模型更清晰,和CoreData的冲突概率更低,而且兼容性更好:
#import <Photos/Photos.h> // 保存视频到相册 [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{ PHAssetCreationRequest *request = [PHAssetCreationRequest creationRequestForAssetFromVideoAtFileURL:videoURL]; } completionHandler:^(BOOL success, NSError *error) { if (success) { NSLog(@"视频保存成功"); } else { NSLog(@"保存失败:%@", error.localizedDescription); } }];
注意:需要在Info.plist中添加NSPhotoLibraryAddUsageDescription字段,说明你请求相册写入权限的原因,否则会导致权限申请失败。
3. 额外检查:确保CoreData操作的线程安全
所有CoreData的操作(读取、写入、更新)都必须在对应的上下文队列中执行,不要跨线程访问NSManagedObject或者上下文,这也能避免和其他框架的线程冲突问题。
内容的提问来源于stack exchange,提问作者fcberg
相关产品推荐
相关产品推荐

