启动UIApplicationShortcutItem

29
我正在使用Swift为我的iOS 9应用程序实现一些3D Touch快速操作,但我遇到了一个奇怪的问题。当我的应用处于后台,并且通过快速操作启动时,一切都按计划进行。当我的应用程序完全关闭(即我从多任务菜单中杀死它),并且我使用快速操作启动时,应用程序会崩溃。由于一旦我杀死应用程序,Xcode中的调试会话就会分离,所以我很难进行调试。是否有一种方法可以像平常一样连接到应用程序进行调试,或者我的代码中是否存在某些问题导致此类情况发生?提前致谢。
代码:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool
{
    var launchedFromShortCut = false

    //Check for ShortCutItem
    if let shortcutItem = launchOptions?[UIApplicationLaunchOptionsShortcutItemKey] as? UIApplicationShortcutItem
    {
        launchedFromShortCut = true
        self.handleShortCutItem(shortcutItem)
    }

    return !launchedFromShortCut
}

func application(application: UIApplication, performActionForShortcutItem shortcutItem: UIApplicationShortcutItem, completionHandler: (Bool) -> Void)
{
    self.handleShortCutItem(shortcutItem)
}

func handleShortCutItem(shortcutItem: UIApplicationShortcutItem)
{
    //Get type string from shortcutItem
    if let shortcutType = ShortcutType.init(rawValue: shortcutItem.type)
    {
        //Get root navigation viewcontroller and its first controller
        let rootNavigationViewController = window!.rootViewController as? UINavigationController


        if let rootViewController = rootNavigationViewController?.viewControllers.first as! LaunchViewController?
        {
            //Pop to root view controller so that approperiete segue can be performed
            rootNavigationViewController?.popToRootViewControllerAnimated(false)

            switch shortcutType
            {
                case .Compose:
                    rootViewController.shouldCompose()
                    break
            }
        }
    }
}

谢谢!


即使应用程序被杀死,您仍然可以查看其崩溃日志文件... - George Asda
你解决了吗?我也遇到了同样的问题。 - theiOSDude
@theiOSDude 没有,我没有。 - Connor Hicks
我认为这篇文章可以回答你的问题。希望能有所帮助。 https://dev59.com/vVwY5IYBdhLWcg3wcHTZ#32772446 - imcc
我也遇到了同样的问题。我尝试使用你上面提供的示例代码,但是在从 killed state 运行时遇到了相同的问题。下面的建议似乎不能捕获从快捷方式启动时的输出。 - ZbadhabitZ
6个回答

64
  1. 在Xcode中,打开“产品(Product)” ->“方案(Schemes)” ->“编辑方案(Edit Schemes)”
  2. 在您的运行方案中,将启动设置更改为“等待可执行文件启动(Wait for executable to be launched)”

现在,如果您打开调试并运行您的应用程序,Xcode将等待您从主屏幕启动应用程序,以便您能够测试使用3D Touch快捷方式项目进行启动。

在Xcode中查看设置截图


1
非常感谢!这让我能够从终止状态测试快速操作。+1 - anon_nerd
2
我该如何将内容打印到控制台? - romero-ios
Helal olsun amk. ADAMSIN! - Ozgur Vatansever
这非常有用!只需确保先在Xcode中运行(cmd+R),然后启动应用程序。 - Marcel Zanoni

27

我终于让它成功了。这是我的 AppDelegate.swift 文件的最终代码;

class AppDelegate: UIResponder, UIApplicationDelegate {

// Properties
var window: UIWindow?
var launchedShortcutItem: UIApplicationShortcutItem?

func applicationDidBecomeActive(application: UIApplication) {

    guard let shortcut = launchedShortcutItem else { return }

    handleShortcut(shortcut)

    launchedShortcutItem = nil

}

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

    // Override point for customization after application launch.
    var shouldPerformAdditionalDelegateHandling = true

    // If a shortcut was launched, display its information and take the appropriate action
    if let shortcutItem = launchOptions?[UIApplicationLaunchOptionsShortcutItemKey] as? UIApplicationShortcutItem {

        launchedShortcutItem = shortcutItem

        // This will block "performActionForShortcutItem:completionHandler" from being called.
        shouldPerformAdditionalDelegateHandling = false

    }

    return shouldPerformAdditionalDelegateHandling
}


func handleShortcut( shortcutItem:UIApplicationShortcutItem ) -> Bool {

    // Construct an alert using the details of the shortcut used to open the application.
    let alertController = UIAlertController(title: "Shortcut Handled", message: "\"\(shortcutItem.localizedTitle)\"", preferredStyle: .Alert)
    let okAction = UIAlertAction(title: "OK", style: .Default, handler: nil)
    alertController.addAction(okAction)

    // Display an alert indicating the shortcut selected from the home screen.
    window!.rootViewController?.presentViewController(alertController, animated: true, completion: nil)

    return handled

}

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

    completionHandler(handleShortcut(shortcutItem))

}

这些内容很大程度上来自于Apple的UIApplicationShortcuts示例代码,虽然我让我的应用程序启动弹出警报来证明它识别了正确的快捷方式,但是这可以适用于你的代码,以弹出视图控制器。

我认为func applicationDidBecomeActive是我缺失的关键部分,并从didFinishLaunchingWithOptions中删除了self.handleShortCut(shortcutItem)(否则似乎会调用两次handleShortCut函数)。


太棒了,很快就会测试。 - Connor Hicks
1
你返回的“handled”值是什么? - LuKenneth
从苹果的例子来看,函数handleShortcut总是返回true,因此很可能"handled"为真。 - zdravko zdravkin

3

针对Swift 4.2版本

   func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.
    var isLaunchedFromQuickAction = false
    if let shortcutItem = launchOptions?[UIApplication.LaunchOptionsKey.shortcutItem] as? UIApplicationShortcutItem {
        isLaunchedFromQuickAction = true
        handleQuickAction(shortcutItem: shortcutItem)
    }

    return isLaunchedFromQuickAction
}

@OmarNShamali 您好 :-) - Atul Pol
我知道这是一个旧帖子,但您是否知道为什么“launchOptions?[UIApplication.LaunchOptionsKey.shortcutItem] as? UIApplicationShortcutItem”即使在应用程序通过快速操作调用时也会评估为nil? - fisch

1

请使用以下方法替换您的didfinishlaunching方法。

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

  if let shortcutItem =
       launchOptions?[UIApplicationLaunchOptionsShortcutItemKey]
       as? UIApplicationShortcutItem {

    handleShortcut(shortcutItem)
    return false
  }
  return true
}

1
我尝试了上述所有方法,但都没有解决问题。然后我尝试在handleShortcut方法中延迟处理快捷键。
self.performSelector("action1", withObject: self, afterDelay: 0.5)

并为每个操作添加了一个方法,它的工作效果非常好。

0

XCode 11.6,Swift 5

我们可以在运行时附加进程。XCode 将等待进程启动,并在手动启动应用程序时附加到它。

XCode -> 调试 -> 按 PID 或名称附加进程 -> ("在弹出窗口中输入应用程序名称")

操作步骤:

  1. 确保应用程序已经在设备或模拟器上新安装。
  2. 关闭应用程序
  3. 在 XCode 中按照上述方式附加进程名称。
  4. 通过所需的快捷方式打开应用程序

P.S:如果您正在使用 SceneDelegate,则可以在以下位置找到 shortcutItem

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
       switch connectionOptions.shortcutItem?.localizedTitle {
       case "Search":
       break
       case "DoSomething":
       break
       default:
       break
       } 
    }

调试愉快 :)

Debug -> Process name

Name of a target


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接