iOS 未调用 UIDocumentPickerDelegate 方法(didPickDocumentsAt)

Posted

技术标签:

【中文标题】iOS 未调用 UIDocumentPickerDelegate 方法(didPickDocumentsAt)【英文标题】:UIDocumentPickerDelegate method(didPickDocumentsAt) not called by iOS 【发布时间】:2019-01-17 11:25:10 【问题描述】:

我有一个关于没有为 DocumentPickerViewController 调用委托方法的查询,这是背景,我只需要从我的文件应用程序中导入任何可用的资源,因此我正在使用 UIDocumentPickerViewController。

我有一个单独的 ViewController,我将 documentPickerViewController 的视图添加为子视图并添加它的委托。我的 ViewController 的代码是这样的。

var documentPickerController: UIDocumentPickerViewController!
  let supportedUTI = [kUTTypeImage,kUTTypeSpreadsheet,kUTTypePresentation,kUTTypeDatabase,kUTTypeFolder,kUTTypeZipArchive,kUTTypeVideo, kUTTypeAudiovisualContent]

documentPickerController = UIDocumentPickerViewController.init(documentTypes: supportedUTI as [String], in: .import)
    documentPickerController.delegate = self
    documentPickerController.allowsMultipleSelection = false
    view.addSubview(documentPickerController.view)

现在我看到pickercontroller 已打开,当我点击取消时会调用documentPickerWasCancelled,但当我选择文件时不会调用documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]

如果我像这样直接显示pickerViewController

UIDocumentPickerViewController *dc = [[UIDocumentPickerViewController alloc] initWithDocumentTypes:[self UTITypes] inMode:UIDocumentPickerModeImport];
    dc.delegate = self;
    [MainVC presentViewController:dc animated:YES completion:nil];

这两个委托方法都被调用得很好。我不明白为什么。有人可以在这里帮我吗!提前致谢!!

【问题讨论】:

您使用的是什么版本的 iosdocumentPicker(_:didPickDocumentsAt:)(URL 数组)是在 iOS 11 中添加的,而 documentPicker(_:didPickDocumentAt:)(单个 URL)当时已被弃用,但已被以前的版本使用。 【参考方案1】:

所以我遇到了完全相同的问题,调用了 documentPickerWasCancelled 委托方法,但不会调用 didPickDocumentsAt

另外值得注意的是,当我将所有委托/演示逻辑移到我的基本视图控制器中时,UIPickerDelegate 方法按预期工作。这让我知道没有任何配置类型问题阻止功能。

我不确定问题出在哪里,但似乎如果文档选择器出现在复杂的视图层次结构上,就会出现问题。

我最终解决此问题的方法是创建一个新窗口并在那里显示文档选择器:

func showDocumentPicker() 

        let documentTypes = ["public.image", "com.adobe.pdf"]

        let picker = UIDocumentPickerViewController(documentTypes: documentTypes, in: .import)
        picker.delegate = self
        picker.allowsMultipleSelection = true
        picker.modalPresentationStyle = .formSheet

        let window = UIWindow(frame: UIScreen.main.bounds)
        let newWindowBaseVC = UIViewController()
        newWindowBaseVC.view.backgroundColor = UIColor.clear
        window.rootViewController = newWindowBaseVC
        window.windowLevel = UIWindow.Level.alert
        window.makeKeyAndVisible()
        newWindowBaseVC.present(picker, animated: false, completion: nil)
    

【讨论】:

【参考方案2】:

答案很简单:这是从 UIViewController 继承的。如果您只是将 viewController 的视图添加到您的视图中,则不会调用委托方法。 ViewController 有自己的生命周期。请在此处阅读:https://developer.apple.com/documentation/uikit/uidocumentpickerviewcontroller

所以,为某种错误表示歉意。当然,您可以添加一个仅显示其视图的子视图控制器。但是:我认为这不应该是用例。它是一个全屏 ViewController 符合苹果本身的设计指南。话虽如此,您应该向它展示:

func addPicker() 
    var documentPickerController: UIDocumentPickerViewController!

    documentPickerController = UIDocumentPickerViewController(documentTypes: [String(kUTTypePDF)], in: .import)
    documentPickerController.delegate = self
    documentPickerController.allowsMultipleSelection = false

    present(documentPickerController, animated: true, completion: nil)

开发人员发现在调用委托之前视图已被关闭,因此提交了一些错误。据我所知,这种行为是在 ios11 中引入的,并且在显示 viewController 时也会发生。我真的不能说这是否已修复,也不能说这种行为是否与将其显示为子视图有关。 (我认为它在某种程度上是固定的,因为它可以与呈现的 viewController 一起使用)

无论如何,您应该按照上面的说明进行展示,然后就可以开始了。

【讨论】:

但是为什么取消回调起作用了?如果我需要实现我想要的方式,你能建议我怎么做吗?谢谢!! 请看我更新的答案。似乎有一个错误。但正如我所写:只是呈现它。【参考方案3】:

原因是如果你不将委托放在函数外的var中,它就会被释放。

如果你在静态环境中,你可以创建一个静态 var 委托:例如 DocumentPickerDelegateClass;否则,在 UIViewController 中只需创建 var 委托: DocumentPickerDelegateClass

在任何情况下,都将 var 放在无法释放的位置。 选择“静态”选项时要小心,必须小心使用。

【讨论】:

以上是关于iOS 未调用 UIDocumentPickerDelegate 方法(didPickDocumentsAt)的主要内容,如果未能解决你的问题,请参考以下文章

未调用 iOS 13 UIPanGestureRecognizer 选择器

未调用 Cordova 插件回调 (iOS)

iOS 7 未调用supportedInterfaceOrientations

未调用 iOS8 接口旋转方法

iOS UITableView cellForRowAtIndexPath 未调用

iOS 10 collectionView:prefetchItemsAt 未调用