iOS11中UIDocumentInteractionController presentPreviewAnimated致App冻结求助
iOS11下UIDocumentInteractionController预览PDF冻结的解决方案
我之前适配iOS11时也碰到过一模一样的问题,给你几个经过验证的排查和解决方向:
先确认文件有效性与访问权限
iOS11对文件系统权限的管控比iOS10严格很多,先排查核心的文件问题:NSURL *fileURL = [NSURL fileURLWithPath:urlPathToDocument]; // 检查文件是否存在 if (![[NSFileManager defaultManager] fileExistsAtPath:fileURL.path]) { NSLog(@"目标PDF文件不存在"); return; } // 检查文件是否可访问 NSError *accessError; if (![fileURL checkResourceIsReachableAndReturnError:&accessError]) { NSLog(@"无法访问PDF文件:%@", accessError.localizedDescription); return; }如果文件在沙盒外(比如iCloud共享目录),还要确认是否已经申请了对应的访问权限。
必须正确实现Delegate的预览控制器回调
iOS11开始,UIDocumentInteractionController对documentInteractionControllerViewControllerForPreview:这个回调的依赖大幅增强——iOS10可能会默认使用当前控制器,但iOS11如果返回nil或不正确的控制器,就会导致预览初始化失败进而冻结。务必实现这个方法:- (UIViewController *)documentInteractionControllerViewControllerForPreview:(UIDocumentInteractionController *)controller { // 返回当前显示的控制器,比如self或者self.navigationController return self; }确保在主线程执行预览调用
虽然你提到试过dispatch_async,但要确认是指定主线程队列(UI操作必须在主线程执行):dispatch_async(dispatch_get_main_queue(), ^{ self.documentInteractionController = [UIDocumentInteractionController interactionControllerWithURL:fileURL]; self.documentInteractionController.delegate = self; [self.documentInteractionController presentPreviewAnimated:YES]; });替换为QLPreviewController(推荐方案)
UIDocumentInteractionController在iOS11存在不少兼容性bug,很多开发者切换到系统原生的QLPreviewController后解决了问题——这个控制器是专门做文件预览的,稳定性更强:// 先导入框架 #import <QuickLook/QuickLook.h> // 初始化并展示预览控制器 QLPreviewController *previewVC = [[QLPreviewController alloc] init]; previewVC.dataSource = self; previewVC.delegate = self; [self presentViewController:previewVC animated:YES completion:nil];然后实现对应的数据源协议方法:
- (NSInteger)numberOfPreviewItemsInPreviewController:(QLPreviewController *)controller { return 1; } - (id<QLPreviewItem>)previewController:(QLPreviewController *)controller previewItemAtIndex:(NSInteger)index { return [NSURL fileURLWithPath:urlPathToDocument]; }排查UI操作冲突
如果上面的方法都无效,检查调用预览时是否有其他正在执行的UI动画、模态弹窗或者阻塞主线程的网络请求。可以尝试在调用预览前暂停其他动画,或者确保当前控制器的view已经完全加载完成。
内容的提问来源于stack exchange,提问作者ElFrancky
相关产品推荐
相关产品推荐

