iOS14可正常访问Caches目录 iOS15移动文件出现513权限错误求助
修复方案
你遇到的是iOS 15对沙盒访问权限和后台下载机制收紧导致的兼容问题,按以下步骤排查即可解决:
- 临时文件访问权限适配:
NSURLSession后台下载完成后返回的临时文件属于跨沙盒文件,iOS15之后必须先调用startAccessingSecurityScopedResource()获取临时文件的访问权限,文件操作完成后必须调用stopAccessingSecurityScopedResource()释放权限,否则就会触发你遇到的Operation not permitted报错。 - 禁止硬编码沙盒路径:不要在代码里写死Caches目录的绝对路径,每次使用前都通过
NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)动态获取当前App的Caches目录路径,iOS15之后App的沙盒根路径会在每次重装、系统升级时动态变更,硬编码路径会直接指向无权限的目录。 - 后台下载回调适配:
NSURLSession初始化时使用的后台标识要固定,不要每次启动App都生成新的标识,否则系统找不到对应的代理对象,就会出现下载完成不触发回调的问题。- 检查AppDelegate中
application:handleEventsForBackgroundURLSession:completionHandler:方法的实现,必须把系统传入的completionHandler保存下来,等所有后台下载任务的回调执行完成后调用该handler,否则iOS15之后会截断后台下载的回调。
- 文件移动逻辑优化:执行移动操作前先判断目标路径的文件是否存在,如果存在先删除旧文件再执行移动,iOS15之后覆盖移动的权限校验规则比iOS14严格很多,提前存在的目标文件会导致移动操作被判定为无权限。
参考代码示例(Objective-C)
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location { // 先获取临时文件安全访问权限 BOOL hasAccess = [location startAccessingSecurityScopedResource]; if (!hasAccess) { // 权限获取失败的错误处理 return; } @try { NSFileManager *fileManager = [NSFileManager defaultManager]; // 动态获取Caches目录路径 NSString *cachesDir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject]; NSString *targetPath = [cachesDir stringByAppendingPathComponent:@"你的目标文件名.xzip"]; // 目标文件存在先删除 if ([fileManager fileExistsAtPath:targetPath]) { [fileManager removeItemAtPath:targetPath error:nil]; } // 执行文件移动 NSError *moveError = nil; BOOL moveSuccess = [fileManager moveItemAtURL:location toURL:[NSURL fileURLWithPath:targetPath] error:&moveError]; if (moveSuccess) { // 下载完成的业务逻辑 } else { // 移动失败的错误处理 NSLog(@"移动文件失败: %@", moveError); } } @catch (NSException *exception) { // 异常捕获处理 } @finally { // 必须释放安全访问权限,避免内存泄露 [location stopAccessingSecurityScopedResource]; } }
内容的提问来源于stack exchange,提问作者DON
相关产品推荐
相关产品推荐

