5

I am new to Swift and have been using SwiftUI, not Storyboard.

I set the UIApplicationShortcutItems in the Info.plist and have two quick actions that are able to present an alert with launchOptions.

I am able to switch-case out the quick actions in SceneDelegate.swift

func windowScene(_ windowScene: UIWindowScene, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) {
    switch shortcutItem.type {
    case "QuickAction1":
        OneView() // What do I do to open this SwiftUI struct View?
        break
    case "QuickAction2":
        SecondView() // What do I do to open this SwiftUI struct View?
        break
    default:
        break
    }
}

What is the proper way to open a particular view from a home quick action using SwiftUI?


ContentView.swift

struct ContentView: View {
    var body: some View {
        NavigationView {
            VStack {
                NavigationLink(destination: OneView())
                NavigationLink(destination: TwoView())
            }
        }
    }
}
user1909186
  • 1,124
  • 2
  • 12
  • 26

1 Answers1

6

Here is possible approach by steps (tested with Xcode 11.2 / iOS 13.2)

  1. Add AppSettings class to store mode of views to be presented by shorcut
    class AppSettings: ObservableObject {
        enum Mode {
            case one
            case two
        }
        @Published var mode: Mode? = nil
    }
  1. make appSettings scene delegate member to access it and in ContentView and in shortcut delegate and pass it in ContentView as environment object
    let appSettings = AppSettings()
    
    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    
        let contentView = ContentView().environmentObject(appSettings)
        // ...
  1. activate corresponding mode in shortcut scene delegate
    func windowScene(_ windowScene: UIWindowScene, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) {
        switch shortcutItem.type {
        case "QuickAction1":
            appSettings.mode = .one
            break
        case "QuickAction2":
            appSettings.mode = .two
            break
        default:
            break
        }
        // ...
    }
  1. Make ContentView present links conditionally based on selected shortcut mode
    struct ContentView: View {
        @EnvironmentObject var appSettings: AppSettings
        
        var body: some View {
            NavigationView {
                VStack {
                    NavigationLink(destination: OneView(),
                                   tag: AppSettings.Mode.one,
                                   selection: $appSettings.mode)
                        { Text("To One") }
                    NavigationLink(destination: TwoView(),
                                    tag: AppSettings.Mode.two,
                                    selection: $appSettings.mode)
                        { Text("To Two") }
                }
            }
        }
    }
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Asperi
  • 228,894
  • 20
  • 464
  • 690
  • It works like a charm! I wasn't sure why you have appDelegate in step 2, so I omitted the constant for now. Could you explain the reason for the reference? Appreciate the thorough answer regardless. – user1909186 Jan 16 '20 at 01:04
  • Removed. `appDelegate` was for another test )) – Asperi Jan 16 '20 at 05:54
  • I have a similar question. I have just one shortcut item that should open a view that would otherwise be navigated to by tapping a NavigationLink. When the view is opened through the shortcut item, I want it to have the Back button with the title of the previous view in the navigation hierarchy. – Dave F May 08 '20 at 03:03
  • You always give great explanations. Question: In step 3, why do you not have `completionHandler(true)` for the 2 cases and false for the default? – David May 01 '21 at 23:33