iOS照片App分享扩展中NSItemProvider加载PHLivePhoto失败问题咨询
系统分享扩展与主App存在独立的沙箱权限边界,跨进程传递的Live Photo内容仅会传递类型标识,不会暴露可直接序列化为PHLivePhoto实例的对象句柄。即便hasItemConformingToTypeIdentifier("com.apple.live-photo")返回true,也无法通过主App中适配PHPicker的loadObject(ofClass: PHLivePhoto.self)逻辑完成加载,这是系统权限设计的限制,并非代码逻辑错误。跨进程加载PHLivePhoto类时会抛出典型错误:
Could not coerce an item to class PHLivePhoto
该错误正是上述权限限制的直接表现。
1. 拆分加载Live Photo组成资源,绕开直接实例化PHLivePhoto的路径
放弃直接通过NSItemProvider加载PHLivePhoto类的原有逻辑,改为分别加载Live Photo对应的两个核心组成单元:
- 针对已获取的
NSItemProvider,分别匹配两类通用UTI:静态照片对应public.image、配套音视频对应public.movie - 改用
loadFileRepresentation(forTypeIdentifier:completion:)接口加载资源,该接口会将系统侧的对应文件拷贝到扩展的临时目录,完全规避跨进程无法序列化系统类实例的限制 - 拿到两个本地临时文件的URL后,通过
PHLivePhoto.requestLivePhoto(with:contentMode:options:)方法,传入匹配的静态图URL和配套视频URL,即可构造出可正常使用的PHLivePhoto对象 - 替换原逻辑中基于
PHAssetResource提取内容的代码为本地文件读取逻辑:扩展进程无系统相册访问权限,绑定系统相册库的PHAssetResource句柄在扩展环境中本身无效,无法读出实际内容。
2. 修正扩展激活规则
原有NSExtensionActivationRule仅声明匹配com.apple.live-photo类型,系统跨进程传递时可能仅传递占位UTI、不附带实际文件句柄。需要调整SUBQUERY匹配规则,兼容同时包含public.image和public.movie的Live Photo分享场景,确保系统将拆分后的实际文件传递给扩展。
3. 配置共享容器打通主App逻辑
配置主App与分享扩展的共享App Group,将从NSItemProvider加载得到的临时文件转存到共享容器目录,既可以避免扩展临时目录被系统提前回收,也能复用主App中基于本地文件的统一处理逻辑。
- 配对静态图和配套视频时,通过系统传递的文件名中的关联标识做匹配,避免错配不同Live Photo的资源
- 分享扩展中禁止直接调用
PHPhotoLibrary相关接口读取资源,该操作会触发权限错误,所有内容处理必须基于NSItemProvider传递的本地文件完成
内容的提问来源于stack exchange,提问作者Chris Prince

