1

I am using UIDocumentInteractionController to save the document at specified URL to iCloud Drive, but the problem is that when I switch back to the app after saving/cancel from iCloud, my original view controller is no longer present, the entire navigation hierarchy is removed and the root view controller is shown.

I am presenting the options in the menu from a view controller that is presented view controller.

extension ADDTextChatViewController: AddReceiverFileDelegate {
    func downloadTapped(url: String?, cell: AddReceiverTableViewCell) {
        guard let urlString = url else {return}
        shareAction(withURLString: urlString, cell: cell)
    }
}

extension ADDTextChatViewController {
    func share(url: URL, cell: AddReceiverTableViewCell) {
        documentInteractionController.url = url
        documentInteractionController.uti = url.typeIdentifier ?? "public.data, public.content"
        documentInteractionController.name = url.localizedName ?? url.lastPathComponent
        documentInteractionController.presentOptionsMenu(from: cell.btnDownload.frame, in: view, animated: true)
    }
    func shareAction(withURLString: String, cell: AddReceiverTableViewCell) {
        guard let url = URL(string: withURLString) else { return }
        URLSession.shared.dataTask(with: url) { data, response, error in
            guard let data = data, error == nil else { return }
            let tmpURL = FileManager.default.temporaryDirectory
                .appendingPathComponent(response?.suggestedFilename ?? "fileName.png")
            do {
                try data.write(to: tmpURL)
            } catch { print(error) }
            DispatchQueue.main.async {
                self.share(url: tmpURL, cell: cell)
            }
            }.resume()
    }
}

extension URL {
    var typeIdentifier: String? {
        return (try? resourceValues(forKeys: [.typeIdentifierKey]))?.typeIdentifier
    }
    var localizedName: String? {
        return (try? resourceValues(forKeys: [.localizedNameKey]))?.localizedName
    }
}

What shall I do in order to remain on the same view controller from which I called this method, after switching back from iCloud?

Kiran Sarvaiya
  • 1,318
  • 1
  • 13
  • 37
Mansi
  • 628
  • 1
  • 8
  • 18
  • Could you please share your code from where you are dismissing the interaction controller. – Dheeraj D Apr 10 '18 at 06:46
  • @DheerajD I haven't added any code for that, it is managed automatically right now or may be I am not able to check whether it is dismissed or not, because when I switch back to my app, my view controller is no longer present, but if I cancel the document interaction controller itself, then the action sheet just dismisses and my view controller is still present – Mansi Apr 10 '18 at 06:46
  • Did you check this: https://stackoverflow.com/questions/29399341/uidocumentinteractioncontroller-swift – Dheeraj D Apr 10 '18 at 06:53
  • can you show your app delegate, what you are doing in applicationDidBecomeActive, applicationWillEnterForeground – Iraniya Naynesh Apr 10 '18 at 06:56
  • @DheerajD but I don't want to share, I want to save to iCloud drive/dropbox whatever suggestions are provided from the action sheet – Mansi Apr 10 '18 at 06:56
  • @IraniyaNaynesh Do I need to do anything there? I am not doing anything in the methods you mentioned – Mansi Apr 10 '18 at 06:57
  • As far I think why your view controller is removed is main issue and root view is coming on a resume, so maybe you are removing or adding while app becomes background or foreground respectively or presenting and dismissing wrongly? – Iraniya Naynesh Apr 10 '18 at 07:00
  • @IraniyaNaynesh yes but I am not removing or adding anything during the app transitions – Mansi Apr 10 '18 at 07:01
  • Please share your cellForRow method code here. Is there anything wrong happing after cell's button tap. – Dheeraj D Apr 10 '18 at 07:03

2 Answers2

4

So it turns out that in order to maintain the navigation stack, you need to pass the navigation controller into the UIDocumentInteractionControllerDelegate method documentInteractionControllerViewControllerForPreview.

In the document for this delegate method it is stated that If presenting atop a navigation stack, provide the navigation controller in order to animate in a manner consistent with the rest of the platform

So here's what my code looks like now, after implementing this delegate method.

extension ADDTextChatViewController: UIDocumentInteractionControllerDelegate {
    func documentInteractionControllerViewControllerForPreview(_ controller: UIDocumentInteractionController) -> UIViewController {
        guard let navVC = self.navigationController else {
            return self
        }
        return navVC
    }
}

And I added

documentInteractionController.presentPreview(animated: true)

instead of

documentInteractionController.presentOptionsMenu(from: view.frame, in: view, animated: true)

which will first show the preview of the document like this (Please see that, this preview will be pushed from my ADDTextChatViewController)

enter image description here

As you can see in the bottom left, the arrow will then provide options such as below, depending upon the document type

enter image description here

So now when I switch back to my application after transitioning to iCloud Drive/ any of the options in the action sheet, my navigation stack is not removed.

I hope this helps someone in future as well.

Mansi
  • 628
  • 1
  • 8
  • 18
1

Could you please try change your code to this and Try:

func share(url: URL, cell : UITableViewCell) {
        documentInteractionController.url = url
        documentInteractionController.uti = url.typeIdentifier ?? "public.data, public.content"
        documentInteractionController.name = url.localizedName ?? url.lastPathComponent
        documentInteractionController.presentOptionsMenu(from: cell.btn.frame, in: view, animated: true)
    } 
Dheeraj D
  • 4,386
  • 4
  • 20
  • 34