Opt Out of Uiscenedelegate/Swiftui on Ios

Opt out of UISceneDelegate/SwiftUI on iOS

While you should embrace using scenes when your app is run under iOS 13 and later, you can fully opt out while you still support iOS 12 or earlier.

  • Completely remove the “Application Scene Manifest” entry from Info.plist.

  • If there is a scene delegate class, remove it.

  • If there are any scene related methods in your app delegate, remove those methods.

  • If missing, add the property var window: UIWindow? to your app delegate.

Your app should now only use the app delegate and under iOS 13 it should have the same life cycle as iOS 12.

Note: None of this is specific to Swift or SwiftUI.

SwiftUI app doesn't run when supporting iOS 13

The StateObject is available from SwiftUI 2.0 (iOS 14) and is designed to work in View, not in class (like SceneDelegate)

For provided scenario a possible solution is to use logicState as just property at top level (in delegate or main view), but inject it completely into child views (instead of just binding) and observe it internally.

So it should look like

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

var loginStatus = UserLoginStatus() // << just hold here

// ...

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
let mainView = MainView(loginStatus: loginStatus) // << here !!


and

struct MainView: View {
@ObservedObject var loginStatus: UserLoginStatus // << injected here

// ...
}

similar can be done in WeatherApp

How do you migrate to the new SwiftUI App Protocol?

You need to follow these steps to migrate a SwiftUI application to the new App life cycle:

  1. Create a new App struct and add the @main annotation:
@main
struct TestApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}

  1. Remove the @main annotation from AppDelegate.

  2. Remove Scene Configuration from Info.plist:

Sample Image


  1. (Optionally) Move AppDelegate/SceneDelegate methods:
  • SwiftUI app life cycle iOS14 where to put AppDelegate code?
  • Is there any way to call SceneDelegate methods in iOS 14 app life cycle?

  1. Now you can remove the AppDelegate and SceneDelegate classes from the project (first make sure the app is indeed working as expected).

How to use old method of setting rootViewController in AppDelegate using Swift

Follow these steps to use AppDelegate and opt-out for SceneDelegate

  1. Go to Info.plist and remove Application Scene Manifest entry from Info.plist.
  2. Remove SceneDelegate.swift
  3. Add var window: UIWindow? in your AppDelegate.swift file
  4. Delete the UISceneSession Lifecycle code from AppDelegate.swift

    import UIKit

    @UIApplicationMain
    class AppDelegate: UIResponder, UIApplicationDelegate {


    var window : UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    // Override point for customization after application launch.
    let mainStoryBoard = UIStoryboard(name: "Main", bundle: Bundle.main)
    let loginController = mainStoryBoard.instantiateViewController(withIdentifier: "HomeViewController")
    self.window?.rootViewController = loginController
    self.window?.makeKeyAndVisible()
    return true
    }
    }

Make sure to give "HomeViewController" storyboardID to your view controller.

This is how your AppDelegate.swift file should look now. You are good to go!

Call external method from AppDelegate swiftui

  1. @EnvironmentObject is only for a SwiftUI View it does not work in a class

  2. @EnvironmentObject has to be injected in the parent View the AppDelegate has no way of knowing about it.

  3. One approach is to have the AppDelegate own the client and then make is available to the subviews of the app1App

Remove from app1App

  var client : Client = Client()

Then change the AppDelegate

class AppDelegate: NSObject, UIApplicationDelegate {
let client : Client = Client()
//the rest of the delegate
}

Then inject the client to the subviews by replacing

MainView().environmentObject(client)

With

MainView().environmentObject(appDelegate.client)

The client will be available by appDelegate.client

This of course assumes the the client is an ObservableObject

SwiftUI, changing a view from scene(:continue

It would be appropriate to use EnvironmentObject in this scenario

class AppState: ObservableObject
@Published var someVar: Sometype
}

class SceneDelegate {
let appState = AppState()

func scene(_ scene: UIScene,
continue userActivity: NSUserActivity) {

// ... other code
appState.someVar = ... // modify
}
}

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {

// .. other code
let contentView = ContentView()
.environmentObject(appState)
//
}
}

struct ContentView: View {
@EnvironmentObject var appState

var body: some View {
VStack {
// ... other code
appState.someVar // use here as needed
}
}
}

ios - Is LaunchScreen required in SwiftUI apps for the AppStore?

A launchscreen is still needed for your application, so the Apple docs are correct.

For SwiftUI applications you can configure your launchscreen through the info.plist provided for your application alternatively you could probably retrofit the storyboard back in.

For guidance on how to configure your launchscreen through the plist file I'd suggest taking a look at this article.



Related Topics



Leave a reply



Submit