I have a working SwiftUI app with a start animation that appears to sometimes cause it to crash - this happens only when the user quits the app completely right before the animation reaches its endpoint and then immediately reopens the app - it skips the launch screen, goes straight to the main one, and then crashes. I have put my code below - thank you for your help.
import SwiftUI
import PDFKit
struct ContentView: View {
@Environment(\.presentationMode) var presentationMode
@Environment(\.scenePhase) var scenePhase
@State var inside = false
@AppStorage("ShowLoadingScreen") var showLoadingScreen = UserDefaults.standard.value(forKey: "ShowingLoadingScreen") as? Bool ?? true
var body: some View {
NavigationView {
ZStack {
Rectangle()
.ignoresSafeArea()
.foregroundColor(Color("LightBlue"))
.navigationTitle("Home")
.navigationBarHidden(true)
VStack {
if inside || !showLoadingScreen{
Spacer()
Text("Bugle") .foregroundColor(Color("DarkBlue"))
.font(Font.custom("Copperplate", size: UIScreen.main.bounds.height * 0.1)) .padding(.top, UIScreen.main.bounds.height * 0.015)
.multilineTextAlignment(.center)
.padding()
Spacer()
.navigationBarHidden(true)
NavigationLink {
MonthlyBugleView()
.navigationTitle("This Month's Bugle")
} label: {
ZStack {
RoundedRectangle(cornerRadius: 100)
.frame(width: UIScreen.main.bounds.width * 0.9, height: UIScreen.main.bounds.height * 0.15)
.opacity(0.8)
Text("This Month's Bugle").font(Font.custom("Copperplate", size: UIScreen.main.bounds.height * 0.05)) .padding(.top, UIScreen.main.bounds.height * 0.015)
.foregroundColor(.white)
.padding()
}
}
Spacer()
NavigationLink {
PDFSwiftUIView(StringToBeLoaded: "SampleLink")
} label: {
ZStack {
RoundedRectangle(cornerRadius: 100)
.frame(width: UIScreen.main.bounds.width * 0.9, height: UIScreen.main.bounds.height * 0.15)
.opacity(0.8)
.foregroundColor(Color("DarkBlue"))
Text("Previous Bugles").font(Font.custom("Copperplate", size: UIScreen.main.bounds.height * 0.05)) .padding(.top, UIScreen.main.bounds.height * 0.015)
.foregroundColor(.white)
.padding()
}
}
Spacer()
NavigationLink {
MoreWinaduStuffView()
.navigationBarHidden(true)
} label: {
ZStack {
RoundedRectangle(cornerRadius: 100)
.frame(width: UIScreen.main.bounds.width * 0.9, height: UIScreen.main.bounds.height * 0.15)
.opacity(0.8)
Text("More Stuff").font(Font.custom("Copperplate", size: UIScreen.main.bounds.height * 0.05)) .padding(.top, UIScreen.main.bounds.height * 0.015)
.foregroundColor(.white)
}
}
Spacer()
} else if showLoadingScreen{
StartAnimationView()
.transition(.opacity)
}
}
.onAppear( perform: {
DispatchQueue.main.asyncAfter(deadline: .now() 3.5){
withAnimation {
inside.toggle()
showLoadingScreen = false
}
}
}
)
}
} .onChange(of: scenePhase) { newPhase in
if newPhase == .inactive {
showLoadingScreen = true
} else if newPhase == .active {
if inside == true{
showLoadingScreen = false
}
} else if newPhase == .background {
showLoadingScreen = true
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
and this is my StartAnimationView
:
import SwiftUI
struct StartAnimationView: View {
let color: UIColor = UIColor(red: 29/255.0, green: 161/255.0, blue: 242/255.0, alpha: 1)
@State var animate: Bool = false
@State var offset: CGFloat = 0
var body: some View {
VStack{
//Content
ZStack{
Color("LightBlue")
Image("sample start")
.resizable()
.scaledToFit()
.padding()
.offset(x: 0, y: offset)
.foregroundColor(.white)
.frame(width: 150, height: 150, alignment: .center)
.scaleEffect(animate ? UIScreen.main.bounds.height * 0.2 : UIScreen.main.bounds.height * 0.0075)
.animation(.easeIn(duration: 3.5), value: animate)
.animation(.easeIn(duration: 0.1), value: offset)
} .ignoresSafeArea()
}.onAppear{
DispatchQueue.main.asyncAfter(deadline: .now() 0.3){
offset = 8
animate.toggle()
}
}
}
}
struct StartAnimationView_Previews: PreviewProvider {
static var previews: some View {
StartAnimationView()
}
}
CodePudding user response:
Your actions in onChange of newPhase may confuse SwiftUI as you ask SwiftUI to show animation when going to inactive or background.