UIDocumentInteractionController Open Menu Cancelled Callback
Asked Answered
M

4

9

I am currently developing an application specifically for iOS7 that utilizes UIDocumentInteractionController open in menu and need a method that notifies me when a user cancels and does not choose an available option.

UIDocumentInteractionControllerDelegate offers:

- (void)documentInteractionControllerDidDismissOptionsMenu:(UIDocumentInteractionController *) controller

but this does not specify whether the user tapped one of the available options or cancel.

Any ideas?

Motherofpearl answered 8/2, 2014 at 0:45 Comment(0)
E
9

NOTE: This will not work for iOS 8 anymore, only iOS7 and earlier

To determine whether the user has canceled the menu or selected an option, you have to make use of the following delegate methods:

1-

- (void)documentInteractionController:(UIDocumentInteractionController *)controller
           didEndSendingToApplication:(NSString *)application
{
    //get called only when the user selected an option and then the delegate method bellow get called
    // Set flag here _isOptionSelected = YES;
    _isOptionSelected = YES;
}

2-

- (void)documentInteractionControllerDidDismissOpenInMenu:(UIDocumentInteractionController *)controller
{
    //called whether the user has selected option or not
    // check your flag here 
    if(_isOptionSelected == NO) {
        //the user has canceled the menu
     }
    _isOptionSelected = NO;
}

iOS 8

For iOS 8 and above, use this method instead of the one in step 2:

- (void)documentInteractionController:(UIDocumentInteractionController *)controller
           didEndSendingToApplication:(NSString *)application
Electrical answered 10/2, 2014 at 17:40 Comment(8)
This won't work, DidDismissOpenInMenu is called before DidEndSendingToApplication. You need to use WillBeginSendingToApplication instead.Weisman
lukech is right. This answer is on the right track but flawed, despite the multiple up votes and bounty. I think Basheer_CAD had the answer, but the post had a typo. You need to check WillBegin... rather than DidEnd... to determine if the user selected an app.Deflected
Thanks @BuvinJ, please edit the answer I will approve your edit, thank youElectrical
I provided an edit. I tried to not change too much! It's similar to what I'm using now for iOS 5 through 8.Deflected
I think my edits are being rejected, as they are disappearing. I don't know how that works. I'm not getting any direct notification of it.Deflected
@BuvinJ, unfortunately your edit was not approved by admins, there was more rejects votes than approvesElectrical
Ok... I don't get that, since my edits are definitively accurate. Thanks for the explanation Basheer!Deflected
@Basheer_CAD, why don't you just edit it instead of waiting that someone else do it and his change get approved? if you edit it it doesn't need approvalMutant
C
0

This will work on iOS7 && iOS8

BOOL didSelectOptionFromDocumentController = NO;//**set this to "NO" every time you present your documentInteractionController too

-(void)documentInteractionController:(UIDocumentInteractionController *)controller willBeginSendingToApplication:(NSString *)application {
    didSelectOptionFromDocumentController = YES;
}


-(void)documentInteractionControllerDidDismissOpenInMenu:(UIDocumentInteractionController *)controller {
    if (didSelectOptionFromDocumentController == NO) {//user cancelled.
        
    }
}
Corduroy answered 25/2, 2016 at 5:28 Comment(0)
M
0

This works for iOS8 & iOS9 for 3rd party apps AND System Apps!

It's not pretty but it works.

Can anyone tell me if this will pass App Review? Not sure as I'm referring to a class name which is not publicly accessible (_UIDocumentActivityViewController). This is Swift 2.2!

NSObject Extension to get a string of the class name:

extension NSObject {
    var theClassName: String {
        return NSStringFromClass(self.dynamicType)
    }
}

Your Viewcontroller where you're calling the UIDocumentInteractionController from:

var appOpened = false
var presentedVCMonitoringTimer: NSTimer!
var docController: UIDocumentInteractionController!

func openDocController() {
    docController = UIDocumentInteractionController(URL: yourURL!)
    docController.UTI = "your.UTI"
    docController.delegate = self
    docController.presentOptionsMenuFromRect(CGRectZero, inView: self.view, animated: true)

    // Check the class of the presentedViewController every 2 seconds
    presentedVCMonitoringTimer = NSTimer.scheduledTimerWithTimeInterval(2, target: self, selector: #selector(self.checkPresentedVC), userInfo: nil, repeats: true)
}

func checkPresentedVC() {
    if let navVC = UIApplication.sharedApplication().keyWindow?.rootViewController as? UINavigationController {
        print(navVC.presentedViewController?.theClassName)
        if navVC.presentedViewController != nil && (navVC.presentedViewController?.theClassName)! != "_UIDocumentActivityViewController" && (navVC.presentedViewController?.theClassName)! != self.theClassName {
            // A system App was chosen from the 'Open In' dialog
            // The presented ViewController is not the DocumentInteractionController (anymore) and it's not this viewcontroller anymore (could be for example the MFMailComposeViewController if the user chose the mail app)
            appOpened = true
            presentedVCMonitoringTimer?.invalidate()
            presentedVCMonitoringTimer = nil
        }
    }
}

func documentInteractionControllerDidDismissOptionsMenu(controller: UIDocumentInteractionController) {
    print("dismissedOptionsMenu")
    presentedVCMonitoringTimer?.invalidate()
    presentedVCMonitoringTimer = nil
    if appOpened {
        // Do your thing. The cancel button was not pressed
        appOpened = false
    }
    else {
        // Do your thing. The cancel button was pressed
    }
}

func documentInteractionController(controller: UIDocumentInteractionController, willBeginSendingToApplication application: String?) {
    // A third party app was chosen from the 'Open In' menu.
    appOpened = true
    presentedVCMonitoringTimer?.invalidate()
    presentedVCMonitoringTimer = nil
}
Mackinnon answered 20/4, 2016 at 21:43 Comment(0)
C
0

For Swift 4, use this:

 func documentInteractionControllerDidDismissOpenInMenu(_ controller: UIDocumentInteractionController) {

        // this function get called when users finish their work, 
        // either for sharing thing within the same app or exit to other app will do
 }

I use it when after users have shared image to Facebook and Instagram.

Changeup answered 12/9, 2017 at 6:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.