PHAsset返回Null但本地标识符有效,求问题排查方案
你遇到的情况确实挺闹心的——明明本地标识符格式看着没问题,应用里别处类似代码都能正常跑,但这里就是拿不到PHAsset,fetch结果的count直接是0。结合你的代码和日志,咱们来拆解下可能的原因和解决方向:
1. 循环赋值的逻辑坑了你
先看这段循环代码:
for (int reyrt = 0; reyrt < self.storeGIF.count; reyrt++) { queue.queuetextimagePath = [self.storeGIF objectAtIndex:reyrt]; }
这里每次循环都会把queue.queuetextimagePath覆盖成当前循环的元素,最后这个属性只会保留self.storeGIF的最后一个元素。如果你的self.storeGIF里有多个元素,那你实际传入fetch的标识符可能根本不是你想测试的那个有效标识符?比如你本来想测第一个元素,但最后存的是最后一个,而最后那个标识符对应的资源已经被删除或者不可访问了。
2. 目标资源已消失或权限不足
从日志里的标识符"857AC3DA-C047-4D88-911B-C5FE227E2B96/L0/001"来看,格式是符合PHAsset本地标识符规范的,但fetch不到的话,大概率是这两个原因:
- 资源已被删除:用户可能已经从相册里删掉了这个资源,对应的标识符自然失效了。你可以把这个标识符复制到应用里其他能正常工作的代码中测试,如果同样拿不到,基本就能确定是资源没了。
- 权限不足:检查你的
Info.plist是否添加了NSPhotoLibraryUsageDescription(iOS 14+还要注意是否需要读取权限,别只加了添加权限的NSPhotoLibraryAddUsageDescription),并且用户已经授权应用访问相册。
3. 试试显式配置PHFetchOptions
你调用fetchAssetsWithLocalIdentifiers:options:时传的是nil,默认选项可能会过滤掉一些特殊资源,比如隐藏资源、连拍序列里的资源。可以试试显式配置选项:
PHFetchOptions *options = [[PHFetchOptions alloc] init]; options.includeHiddenAssets = YES; // 包含系统标记为隐藏的资源 options.includeAllBurstAssets = YES; // 包含连拍组里的所有资源 PHFetchResult *assetsFetchResult = [PHAsset fetchAssetsWithLocalIdentifiers:identifiers options:options];
说不定目标资源刚好是被默认选项过滤掉的类型。
4. 检查Core Data存储的标识符是否准确
你把标识符存在Core Data的Queue实体里,有没有可能存储时就出了问题?比如字符串有多余的空格、换行符,或者编码错误?建议在存储前打印[self.storeGIF objectAtIndex:reyrt]的内容,和日志里的标识符对比,确保完全一致。
最后给个小优化建议:如果要存储多个标识符,别用单个字符串属性,改成数组类型的属性(比如把queuetextimagePath改成queuetextimagePaths,类型设为NSArray),循环时把元素添加进去,这样既能一次性fetch多个资源,也不会出现覆盖赋值的问题。
内容的提问来源于stack exchange,提问作者Marc Matteo

