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()
}
}
}
Also, here is a screenshot of the Info.plist file, specifically expanding the related area:
CodePudding user response:
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
CodePudding user response:
According to Apple docs, StateObject
is only available on iOS 14 .