ios - Dynamically edit 3d touch shortcut list

倖福魔咒の 提交于 2019-11-30 09:26:58

There are two ways to create shortcuts - dynamic and static.

  • Static are added to the plist and never change.
  • Dynamic can be added and removed in code.

It sounds like you want a dynamic shortcut, so here's roughly how you would do that:

To add:

if #available(iOS 9.0, *) {
    if (UIApplication.sharedApplication().shortcutItems?.filter({ $0.type == "com.app.myshortcut" }).first == nil) {
        UIApplication.sharedApplication().shortcutItems?.append(UIMutableApplicationShortcutItem(type: "com.app.myshortcut", localizedTitle: "Shortcut Title"))
    }
}

To remove:

if #available(iOS 9.0, *) {
    if let shortcutItem = UIApplication.sharedApplication().shortcutItems?.filter({ $0.type == "com.app.myshortcut" }).first {
        let index = UIApplication.sharedApplication().shortcutItems?.indexOf(shortcutItem)

        UIApplication.sharedApplication().shortcutItems?.removeAtIndex(index!)
    }
}

You can then handle the shortcut by checking for it in the app delegate method:

@available(iOS 9.0, *)
func application(application: UIApplication, performActionForShortcutItem shortcutItem: UIApplicationShortcutItem, completionHandler: (Bool) -> Void) {
    if shortcutItem.type == "com.app.myshortcut" {
        // Do something
    }
}

Don't forget to check for iOS9 and 3d Touch compatibility.

You can find Apple developer 3d touch pages here:

https://developer.apple.com/ios/3d-touch/

And specifically dynamic shortcuts here:

https://developer.apple.com/library/ios/samplecode/ApplicationShortcuts/Listings/ApplicationShortcuts_AppDelegate_swift.html#//apple_ref/doc/uid/TP40016545-ApplicationShortcuts_AppDelegate_swift-DontLinkElementID_3

Here's a handy class to trigger segues off of 3D touch off of your app icon. Of course you could trigger any action, but this is probably the most common. It then syncs itself when the app comes up or goes to the background. I'm using this to trigger a "My Projects" section only after the user has generated one (VisualizerProject.currentProject.images.count > 0).

class AppShortcut : UIMutableApplicationShortcutItem {
    var segue:String

    init(type:String, title:String, icon:String, segue:String) {
        self.segue = segue
        let translatedTitle = NSLocalizedString(title, comment:title)
        let iconImage = UIApplicationShortcutIcon(templateImageName: icon)
        super.init(type: type, localizedTitle:translatedTitle, localizedSubtitle:nil, icon:iconImage, userInfo:nil)
    }
}

class AppShortcuts {

    static var shortcuts:[AppShortcut] = []

    class func sync() {

        var newShortcuts:[AppShortcut] = []

        //reverse order for display
        newShortcuts.append(AppShortcut(type: "find-color", title: "Find Color", icon:"ic_settings_black_24px", segue: "showColorFinder"))

        newShortcuts.append(AppShortcut(type: "samples", title: "Sample Rooms", icon:"ic_photo_black_24px", segue: "showSamples"))

        //conditionally add an item like this:
        if (VisualizerProject.currentProject.images.count > 0) {
            newShortcuts.append(AppShortcut(type: "projects", title: "My Projects", icon:"ic_settings_black_24px", segue: "showProjects"))
        }

        newShortcuts.append(AppShortcut(type: "visualizer", title: "Paint Visualizer", icon:"ic_photo_camera_black_24px", segue: "showPainter"))

        UIApplication.sharedApplication().shortcutItems = newShortcuts
        shortcuts = newShortcuts
    }

    class func performShortcut(window:UIWindow, shortcut:UIApplicationShortcutItem) {

        sync()

        if let shortcutItem = shortcuts.filter({ $0.type == shortcut.type}).first {

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

                landingViewController.performSegueWithIdentifier(shortcutItem.segue, sender: self)
            }
        }
    }
}

Then in your app delegate, add the sync and perform shortcut calls

func applicationDidEnterBackground(application: UIApplication) {
    AppShortcuts.sync()
}

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.

    AppShortcuts.sync()
}

@available(iOS 9.0, *)
func application(application: UIApplication, performActionForShortcutItem shortcutItem: UIApplicationShortcutItem, completionHandler: (Bool) -> Void) {

    if let window = self.window {
         AppShortcuts.performShortcut(window, shortcut: shortcutItem)
    }
}

I assume you're talking about the so-called Quick Actions a user can call by force-touching your app's icon on his home screen. You can dynamically create and update them right from your code. The best way to learn about all the possibilities is looking at Apple's sample code.

 [UIApplication sharedApplication].shortcutItems = @[];

worked for me. the other answer that suggests removing something from the array didn't work as shortcutItems is not mutable.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!