如何在Objective-C中通过URL路径从iOS相册获取图片?
嘿,这个问题我太熟了!刚好可以给你理清楚怎么用Objective-C实现,毕竟ALAssets框架确实早就被苹果弃用了,现在官方都是推荐用Photos框架来处理相册资源的。
首先得敲个重点:直接保存相册图片的文件URL是非常不可靠的——iOS的照片库属于系统沙盒外的资源,你的应用没有直接访问权限,而且系统可能会在后台移动图片文件,导致之前保存的URL直接失效。所以先给你分两种情况解决:
用Objective-C从Core Data加载相册图片
情况1:你已经存了URL,应急加载(不推荐长期用)
如果你的URL是从旧版UIImagePickerController的UIImagePickerControllerReferenceURL拿到的(这个key在iOS11+已经被弃用了),这个URL其实指向的是旧ALAsset资源,现在可以通过Photos框架把它转成PHAsset再加载:
// 从Core Data取出你存的URL字符串 NSString *savedURLString = @"这里替换成你的URL字符串"; NSURL *assetURL = [NSURL URLWithString:savedURLString]; // 用Photos框架根据旧URL找对应的PHAsset PHFetchResult *fetchResult = [PHAsset fetchAssetsWithALAssetURLs:@[assetURL] options:nil]; if (fetchResult.count > 0) { PHAsset *targetAsset = fetchResult.firstObject; // 配置图片请求选项:异步请求+高质量格式 PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init]; options.synchronous = NO; options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat; // 请求图片,这里用原图尺寸,你也可以改成自己需要的大小 [[PHImageManager defaultManager] requestImageForAsset:targetAsset targetSize:PHImageManagerMaximumSize contentMode:PHImageContentModeDefault options:options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) { if (result) { // 必须切回主线程更新UI! dispatch_async(dispatch_get_main_queue(), ^{ self.yourImageView.image = result; }); } else { NSLog(@"糟了,图片加载失败,可能资源已经被删除了"); } }]; } else { NSLog(@"没找到对应的相册资源哦"); }
但还是要强调:这种方法只是应急,一旦用户删除图片或者系统清理资源,还是会加载失败,强烈建议你迁移到保存PHAsset的localIdentifier,这才是稳定的方案。
情况2:正确的姿势——保存localIdentifier,用Photos框架加载
这是苹果官方推荐的稳定方案,分两步走:
第一步:选图时保存localIdentifier到Core Data
在UIImagePickerController的代理方法里,拿到选中图片的PHAsset,把它的localIdentifier存到Core Data:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<UIImagePickerControllerInfoKey,id> *)info { // 获取选中的PHAsset PHAsset *selectedAsset = info[UIImagePickerControllerPHAsset]; if (selectedAsset) { // 拿到稳定的localIdentifier NSString *assetID = selectedAsset.localIdentifier; // 这里写你的Core Data保存逻辑,比如创建实体对象、赋值、保存上下文 // 举个简单例子: // YourImageEntity *entity = [NSEntityDescription insertNewObjectForEntityForName:@"YourImageEntity" inManagedObjectContext:yourContext]; // entity.assetID = assetID; // NSError *error; // [yourContext save:&error]; } [picker dismissViewControllerAnimated:YES completion:nil]; }
第二步:在另一个VC里加载图片
从Core Data取出localIdentifier,用Photos框架查询PHAsset并请求图片:
// 从Core Data取出保存的localIdentifier NSString *savedAssetID = @"这里替换成你的标识符"; // 根据ID找PHAsset PHFetchResult *fetchResult = [PHAsset fetchAssetsWithLocalIdentifiers:@[savedAssetID] options:nil]; if (fetchResult.count > 0) { PHAsset *targetAsset = fetchResult.firstObject; PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init]; options.synchronous = NO; // 如果需要原图,把resizeMode设为None options.resizeMode = PHImageRequestOptionsResizeModeNone; // 可以根据需求设置目标尺寸,比如屏幕宽高 CGSize targetSize = [UIScreen mainScreen].bounds.size; [[PHImageManager defaultManager] requestImageForAsset:targetAsset targetSize:targetSize contentMode:PHImageContentModeAspectFill options:options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) { if (result) { dispatch_async(dispatch_get_main_queue(), ^{ self.targetImageView.image = result; }); } else { NSLog(@"图片加载失败啦"); } }]; } else { NSLog(@"找不到对应的相册资源哦"); }
必看注意事项
- 记得在
Info.plist里添加相册权限描述:NSPhotoLibraryUsageDescription(如果需要往相册存图还要加NSPhotoLibraryAddUsageDescription),不然应用会直接崩溃! - 要导入Photos框架:
#import <Photos/Photos.h>。 - 图片请求是异步的,一定要切回主线程更新UI,不然会出各种UI异常。
内容的提问来源于stack exchange,提问作者amirtmgr
相关产品推荐
相关产品推荐

