0

Hi i have a problem with my App i have added 3D Touch Quick actions and my problem is when my app is not in multitasking then not open the Share sheet in my app have anyone a idea how can i fix the problem thats my code the problem is only in the share quick action on the info view and the problem quick action work it fine.

// AppDelegate.swift

import UIKit import MessageUI

@UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate, MFMailComposeViewControllerDelegate {

var window: UIWindow?

enum QuickActionType : String {
    case viewControllerInfo = "com.example.infoView"
    case share = "com.example.share"
    case problem = "com.example.problem"

}

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    var QuickAction = false

    if let shortcutItem = launchOptions?[UIApplicationLaunchOptionsShortcutItemKey] as? UIApplicationShortcutItem{
        QuickAction = true
        handleQuickAction(shortcutItem)
    }

    return !QuickAction

}

func application(application: UIApplication, performActionForShortcutItem shortcutItem: UIApplicationShortcutItem, completionHandler: (Bool) -> Void) {
    let handledQuickAction = handleQuickAction(shortcutItem)
    completionHandler(handledQuickAction)

}

func mailComposeController(controller: MFMailComposeViewController, didFinishWithResult result: MFMailComposeResult, error: NSError?) {
    if error != nil {
        print(error?.localizedDescription)
    }

    self.window?.rootViewController?.dismissViewControllerAnimated(true, completion: nil)

}


func applicationWillResignActive(application: UIApplication) {
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}

func applicationDidEnterBackground(application: UIApplication) {
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}

func applicationWillEnterForeground(application: UIApplication) {
    // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}

func applicationDidBecomeActive(application: UIApplication) {
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}

func applicationWillTerminate(application: UIApplication) {
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}

func handleQuickAction(shortcutItem: UIApplicationShortcutItem) -> Bool {

    var handled = false

    if let shortCutType = QuickActionType.init(rawValue: shortcutItem.type){
        let rootNavigationViewController = window!.rootViewController as? UINavigationController
        let rootViewController = rootNavigationViewController?.viewControllers.first as UIViewController?

        rootNavigationViewController?.popToRootViewControllerAnimated(false)

        switch shortCutType {

            // Quick Action Info

        case .viewControllerInfo:
            handled = true
            rootViewController?.performSegueWithIdentifier("infoView", sender: nil)


        case .share:
            handled = true

            let shareItems = ["hello world"]

            let activityViewController = UIActivityViewController(activityItems: shareItems, applicationActivities: nil)

            self.window?.rootViewController?.presentViewController(activityViewController, animated: true, completion: nil)

            // Quick Action Problem

        case .problem:
            handled = true

            let mailController = MFMailComposeViewController()
            mailController.mailComposeDelegate = self
            mailController.setToRecipients(["example@gmail.com"])
            mailController.setSubject("App Bug")
            mailController.setMessageBody("(Your Problem)

            self.window?.rootViewController?.presentViewController(mailController, animated: true, completion: nil)

        }
    }

    return handled

}

}

chris188
  • 11
  • 3

2 Answers2

0

Try adding a slight delay before handling your quick action and see if that helps. I found out when I was executing my quick actions that they wouldn't work 100% reliably without a small delay. I currently use 0.5 seconds. You can do something like this (in obj-c):

[self.performSelector:@selector(doAction:) withObject:obj afterDelay:0.5];

or in swift:

self.performSelector("doAction:", withObject: obj, afterDelay: 0.5)

This may or may not help in your case, but it did in mine and I filed a radar on it that I haven't heard back from yet.

Greg G
  • 461
  • 4
  • 14
0

Hey you need to show the ViewController on the top of the current ViewController try that. This is a simple Extension add this on your AppDelegate for example.

extension UIWindow {

func visibleViewController() -> UIViewController? {
    if let rootViewController: UIViewController  = self.rootViewController {
        return UIWindow.getVisibleViewControllerFrom(rootViewController)
    }
    return nil
}

class func getVisibleViewControllerFrom(vc:UIViewController) -> UIViewController {

    if vc.isKindOfClass(UINavigationController.self) {

        let navigationController = vc as! UINavigationController
        return UIWindow.getVisibleViewControllerFrom( navigationController.visibleViewController!)

    } else if vc.isKindOfClass(UITabBarController.self) {

        let tabBarController = vc as! UITabBarController
        return UIWindow.getVisibleViewControllerFrom(tabBarController.selectedViewController!)

    } else {

        if let presentedViewController = vc.presentedViewController {

            return UIWindow.getVisibleViewControllerFrom(presentedViewController.presentedViewController!)

        } else {

            return vc;
        }
    }
}}

Right now you can check the visible Viewcontroller like that

self.window?.visibleViewController()?.presentViewController(yourviewcontroller, animated: true, completion: nil)

I hope this will help you.

BilalReffas
  • 8,132
  • 4
  • 50
  • 71
  • isKindOfClass? Are you serious? :D This is the most objc-like-swift-code I have seen so far. Where did you learn that? ;) – Ben Nov 24 '15 at 21:34
  • Yes as you can see it works to check the current visible viewcontroller – BilalReffas Nov 24 '15 at 21:36
  • Okay thats true but it's not written by myself just copy it from here..a small extension that works well – BilalReffas Nov 24 '15 at 21:39
  • I did some changes. Next work would be to eliminate the exclamation marks. – Ben Nov 24 '15 at 21:43
  • Okay that is really awesome thank you for that:) But really I dont think so stackoverflow is there to show people the best optimized source code.:D I think the most important point is to help and to fix the issues. Just to get something to work. :) – BilalReffas Nov 24 '15 at 21:46
  • Definitely! So for chris your answer maybe is great (if that's his problem what it is not I guess). But imagine more and more people are having this problem and they ask google for it. Think about what they will find :) I think it's the best to give the best possible answer and it's ok if it's a community answer where you give the working answer and I correct the code style :) Everybody learns something -> win! – Ben Nov 24 '15 at 21:54
  • Okay I agree of course it would be the best answer correct code + correct code style. But this is not for everyoje possible:D For example I am sometimes to lazy for well written code :D – BilalReffas Nov 24 '15 at 21:56
  • It's a shame to be too lazy for writing good code. Especially for a software developer ;) – Ben Nov 24 '15 at 22:01
  • Yeah but it depends on the situation. Real Project or people who want a fast answer... – BilalReffas Nov 24 '15 at 22:03
  • In each case, I did the work for you, please accept my edits, do that others can benefit from it. – Ben Nov 25 '15 at 06:12