iOS开发无法访问Adobe Reader分享的PDF路径,权限如何配置?
问题根因分析
- 你拿到的
file://路径属于Adobe Reader应用自己的沙盒目录,iOS沙盒机制默认禁止跨应用直接访问其他App的私有目录,和你自己配置的共享容器没有关系,共享容器只适用于你自己开发的同团队ID下的App组共享场景,无法覆盖第三方App分享的临时文件访问。 - 从其他App分享文件到你的App时,系统给的URL默认是临时授权的,你必须在分享回调的生命周期内立刻完成文件的拷贝操作,把文件存到你自己App的沙盒或者App Group容器里,授权才会生效,如果你只是存了这个URL后续再访问,临时授权已经失效,就会提示文件不存在或者无权限。
- Adobe Reader的分享逻辑和系统文件App、浏览器不同:大部分App分享时会把文件拷贝到系统提供的你的App的临时收件箱目录(路径一般是你的App沙盒下的
tmp/Inbox/),但Adobe Reader是把文件放在自己的tmp目录下给你临时授权,授权有效期更短,只要分享回调执行完就会立即失效,也不会主动拷贝到你的App的Inbox目录。
修复方案
- 不需要额外配置entitlements或者权限,你只需要在处理分享的回调方法(比如
UIApplicationDelegate的application:openURL:options:或者SceneDelegate对应的方法)里,拿到URL后第一时间先调用startAccessingSecurityScopedResource方法获取访问权限,示例代码:
// Objective-C示例 BOOL canAccess = [url startAccessingSecurityScopedResource]; if (canAccess) { // 执行文件拷贝操作,把文件存到你自己的沙盒/Group容器 NSError *copyError = nil; NSURL *destUrl = [[NSFileManager.defaultManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] firstObject]; destUrl = [destUrl URLByAppendingPathComponent:url.lastPathComponent]; [NSFileManager.defaultManager copyItemAtURL:url toURL:destUrl error:©Error]; // 访问结束必须调用对应停止方法释放资源 [url stopAccessingSecurityScopedResource]; }
// Swift示例 let canAccess = url.startAccessingSecurityScopedResource() if canAccess { defer { url.stopAccessingSecurityScopedResource() } let destUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0].appendingPathComponent(url.lastPathComponent) try? FileManager.default.copyItem(at: url, to: destUrl) }
- 不要长期存储你拿到的第三方App分享的原始URL,所有分享来的文件都必须拷贝到你自己可控的目录后再做后续处理,原URL在分享回调结束后就会失效。
- 如果调用
startAccessingSecurityScopedResource返回NO,检查你App的Info.plist里是否已经开启UIFileSharingEnabled(文件共享)和LSSupportsOpeningDocumentsInPlace配置:如果不需要原地编辑第三方文件,建议把LSSupportsOpeningDocumentsInPlace设为NO,这样所有分享来的文件都会自动拷贝到你App的tmp/Inbox目录,不需要额外处理安全域访问权限。
内容的提问来源于stack exchange,提问作者BT b killin me
相关产品推荐
相关产品推荐

