Search code examples
iosswiftuikiturl-schemewidgetkit

Problems starting ViewController from a widget click


I have a widget and want to open a particular ViewController when clicking on it. I've read all the documentation and questions on SO regarding the topic, and can't figure out why it isn't working. When clicking the widget, it always opens the default ViewController.

Here's the code for the WidgetView.

struct WidgetAdapter : View {

    let entry: TimeLine.Entry
    @Environment(\.widgetFamily) var family

    @ViewBuilder
    var body: some View {
        switch family {
        case .systemSmall:
            SmallView(...).widgetURL(URL(string: "fcv://open_activity"))
        case .systemMedium:
            MediumView(...).widgetURL(URL(string: "fcv://open_activity"))
        default:
            LargeView(...).widgetURL(URL(string: "fcv://open_activity"))
        }
    }
}

Here the AppDelegate method for managing URLs.

func application(_ application: UIApplication, open
                    url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool{ 
    if url.scheme == "fcv"{
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let vc = storyboard.instantiateViewController(withIdentifier: "WidgetActivity") as! WidgetActivityController
        self.window?.rootViewController = vc
        self.window?.makeKeyAndVisible()
    }
    return true
}

I also tried implementing the respective method for the SceneDelegate, I added the url scheme to the URL Types in project info, I added the LSApplicationQueriesSchemes item to the info.plist, used Link instead of .widgetURL... And it didn't work even once. I also think that the method in the AppDelegate is not being called, however, I checked for the cases were that can happen and they don't come to case.

Any help would be appreciated.


Solution

  • I solved the same problem by finding current rootViewController and pushing the view I need:

    let rootViewController = window!.rootViewController as! UINavigationController
    let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)let profileViewController = mainStoryboard.instantiateViewController(withIdentifier: "MainVC") as! CombinedMainVC
    rootViewController.pushViewController(profileViewController, animated: false)
    

    It is always UINavigationController in my case, so I push a new VC, in your case you could present it.

    I use the same method in AppDelegate, so there could be a problem with your if statement. Where do you set a scheme for a widget URL? Maybe you could just check URL string:

    if url.absoluteString.prefix(3) == "fcv" { }