0

When I open the App from my Today Extension with this method :

open func open(_ URL: URL, completionHandler: ((Bool) -> Void)? = nil)

My app's life cycle goes this way :

  • didFinishLaunchingWithOptions
  • viewDidLoad (initial ViewController)
  • openURL

This annoys me because I want to set my launchState variable to widget and do custom logic in my initial ViewController which I can't if the openURL method is the last one triggered.

How can I handle this scenario ?

EDIT:

The user can open the App from the Today Extension, or the Classic launch. In the viewDidLoad of the rootViewController I am doing this :

fileprivate func prepareCityToLaunch() {

    switch launchState {
         case .widget:
             launchCity.getWidgetCity()
         case .classic:
             launchCity.getLaunchCity()
    }
}

Which is an enum, by default it is set to .classic, and I am setting it to .widget in the openURL method.

This methods return the appropriate City object to request for thank to delegation.

I can't wait for the Notification from openURL because in this viewController I don't know yet if the App is open from Widget or from Classic launch and because the launchState is set to classic by default, it will always get the city as if the App is launched in the classic way.

That is why I wanted to set the launchState first in the openURL method, then in my viewDidLoad everything would have been set correctly.

Is it understandable ?

Ankit Srivastava
  • 12,347
  • 11
  • 63
  • 115

3 Answers3

3

Here is an alternative and better solution. Add the following lines in didFinishLaunchingWithOptions and make a check for bundle identifier of your today widget.

    if let value = launchOptions?[UIApplication.LaunchOptionsKey.sourceApplication] as? String, value == "com.company.app.todayWidget" {
        //Launched via today widget
    }
Ankit Srivastava
  • 12,347
  • 11
  • 63
  • 115
2

You need to show a loader/empty value inside the vc , then using NSNotificationCenter from inside openURL to set needed value

OR

Set a suite shared user default between your app and the widget to know that and give it a value before the line that directs to the app , and check it's value inside viewDidLoad of the vc , then set it to nil

Shehata Gamal
  • 98,760
  • 8
  • 65
  • 87
0

When using SwiftUI, add .widgetURL(deeplinkURL) to it and handle it inside of your main app's SceneDelegate.

struct MyWidget: View {

  private static let deeplinkURL = URL(string: "some-deeplink-scheme://optionalOtherStuff")!

  var body: some View {
    Text(entry.date, style: .time)
      .widgetURL(deeplinkURL)
  }
}

Also make sure to add that custom url scheme to your project settings inside of your app's target's info tab under URL Types

Add custom url scheme to project settings for deeplink handling

For a more complete answer see https://stackoverflow.com/a/63715553/1898677 and https://www.donnywals.com/handling-deeplinks-in-your-app/

laka
  • 644
  • 8
  • 23