skip to Main Content

App was working fine when the deployment target was 15.2, but then I needed to change the deployment target to iOS 13 to support more devices. Still works fine on iOS 14+, but it crashes with exception Thread 1: signal SIGABRT, when it runs on iOS 13 on the simulator. Console shows no debug information:

CoreSimulator 802.6 - Device: iPhone 11 (iOS 13.0) (6CCC2B89-002B-4E83-8175-C244984BFC46) - Runtime: iOS 13.0 (17A577) - DeviceType: iPhone 11
Message from debugger: Terminated due to signal 9

Here are the related segments of the WeatherApp.swift file code along with a screenshot of the error:

@main
struct WeatherAppWrapper {
    static func main() {
        if #available(iOS 14.0, *) {
            WeatherApp.main()
        }
        else {
            UIApplicationMain(CommandLine.argc, CommandLine.unsafeArgv, nil, NSStringFromClass(SceneDelegate.self))
        }
    }
}

struct WeatherApp: App {
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    @StateObject var loginStatus = UserLoginStatus()
    
    @available(iOS 14.0, *)
    var body: some Scene {
        WindowGroup {
            NavigationView{
                if Methods.UserAccount.getFromUserDefaults()["username"] != nil {
                    MainView(loggedIn: $loginStatus.loggedIn)
                    LoginView(username: "", password: "", loggedIn: $loginStatus.loggedIn)
                } else {
                    LoginView(username: "", password: "", loggedIn: $loginStatus.loggedIn)
                    MainView(loggedIn: $loginStatus.loggedIn)
                }
            }
        }
    }

    class AppDelegate: NSObject, UIApplicationDelegate, UNUserNotificationCenterDelegate, MessagingDelegate {
        func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

            //Some app-specific setup code
            ...
            
            return true
        }
        
    }
}

class UserLoginStatus: ObservableObject {
    @Published var loggedIn: Bool {
        didSet {
            print("The value of loggedIn changed from (oldValue) to (loggedIn)")
        }
    }
    
    init () {
        loggedIn = false
    }
}

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?

    @StateObject var loginStatus = UserLoginStatus()

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        let mainView = MainView(loggedIn: $loginStatus.loggedIn)
        let loginView = LoginView(username: "", password: "", loggedIn: $loginStatus.loggedIn)

        if let windowScene = scene as? UIWindowScene {
            let window = UIWindow(windowScene: windowScene)
            
            if Methods.UserAccount.getFromUserDefaults()["username"] != nil {
                window.rootViewController = UIHostingController(rootView: mainView)
            } else {
                window.rootViewController = UIHostingController(rootView: loginView)
            }
            
            self.window = window
            window.makeKeyAndVisible()
        }
    }
    
}

enter image description here

Also, here is a screenshot of the Info.plist file, specifically expanding the related area:

enter image description here

2

Answers


  1. According to Apple docs, StateObject is only available on iOS 14+.

    Login or Signup to reply.
  2. 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

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search