UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

SOLVED: SwiftUI - How To Show A SwiftUI "Whats new" Screen only when App Launches after update?

Forums > SwiftUI

How can a "Whats new Screen" Only be displayed after an apps launch or after a update was detected?

Apple does this when bigger updates happen (or at launch) which is quite nice from a users point.

I have already Created the View (WhatsNew) but i cannot manage to get it showing when app launches first time or at update, it just starts in the default "ContentView" or the "Whats new" View.

My knowlege is limeted in the SceneDelegate also found a page which clears up the topic a bit for me, but I am stuck at step 3... Were should this be placed?

class ViewRouter: ObservableObject {

    @Published var currentPage: String

}

https://blckbirds.com/post/how-to-show-a-swiftui-onboarding-screen-only-when-to-app-launches-for-the-first-time/ Also im not sure if the message also gets displayd when the app launches after an update.

Is there maby a different way which is easyer?

Thanks for taking your time. Appreciate it. Pascal

3      

If you implement it as in the link you're refering to it will only show it once you started the app the first time, but not anymore after updates.

To always get the "whats new" screen you need to also work with the version of the app.

I would implement it the following way:

  1. Somewhere in your app you need to define a constant with your current Version Number
  2. When opeing the app check the version you saved in UserDefaults with the latest app version you specify in the code
  3. If saved version does match the current version the user have been here already after update
  4. If saved version does not match the current version, trigger the "Whats new" screen and save the currentVersion to UserDefaults
func getCurrentAppVersion() -> String {
        let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"]
        let version = (appVersion as! String)

        return version
    }

func checkForUpdate() {
        let version = getCurrentAppVersion()
        let savedVersion = UserDefaults.standard.string(forKey: "savedVersion")

        if savedVersion == version {
            print("App is up to date!")
        } else {

            // Trigger to show the "Whats new" screen

            // Save the current version to UserDefaults
            UserDefaults.standard.set(version, forKey: "savedVersion")
        }
    }

4      

It seems as something is happening because the app Takes longer to launch.

But im not sure were my mistake is, or if i have used the code correct. Tryed to follow all the Steps.

I have made the AppLaunch file with the Code: Managed that it complies with the @ViewBuilder, but it doesn’t want to Work. Not sure if this is a good way or better to add to the WhatsNew View?

struct AppLaunch: View {
    @EnvironmentObject var userData: UserData

    let version = "1.2.0"

@ViewBuilder
var body: some View {

func getCurrentAppVersion() -> String {
        let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"]
        let version = (appVersion as! String)

        return version
    }

func checkForUpdate() {
        let version = getCurrentAppVersion()
        let savedVersion = UserDefaults.standard.string(forKey: "savedVersion")

        if savedVersion == version {
            print("App is up to date!")
        } else {
            WhatsNew()

//           Or should I rather use? 

//            WhatsNew.version == "WhatsNew" {
//                WhatsNew()
//            }

            UserDefaults.standard.set(version, forKey: "savedVersion")
        }
    }

}
}

Added the Version in my UserData file Which i don’t know if this is needed...?

class UserData : ObservableObject {

    private static let userDefaultPrice = "Price"
    private static let userDefaultRent = "Rent"
    private static let userDefaultArea = "Area"
    private static let userDetaultversion = "savedVersion"

    @Published var Price = UserDefaults.standard.string(forKey: UserData.userDefaultPrice) ?? "" {
    didSet {
      UserDefaults.standard.set(self.Price, forKey: UserData.userDefaultPrice)
      }
    }

    @Published var Rent = UserDefaults.standard.string(forKey: UserData.userDefaultRent) ?? "" {
    didSet {
      UserDefaults.standard.set(self.Rent, forKey: UserData.userDefaultRent)
      }
    }

    @Published var Area = UserDefaults.standard.string(forKey: UserData.userDefaultArea) ?? "" {
      didSet {
       UserDefaults.standard.set(self.Area, forKey: UserData.userDefaultArea)
      }
    }

        @Published var version = UserDefaults.standard.string(forKey: UserData.userDetaultversion) ?? "1.1.0" {
     didSet {
      UserDefaults.standard.set(self.version, forKey: UserData.userDetaultversion)
     }
    }

  private var canc: AnyCancellable!
}

The "WhatsNew" View (which should only be visible at App updated):


struct WhatsNew: View {
    @Environment(\.presentationMode) var presentationMode

    var body: some View {
        VStack{
             Spacer()
        HStack{
            VStack{
                Text("What's New")
                    .fontWeight(.bold)
            }
                VStack(alignment: .leading){
                HStack{
                    Image (systemName: "paintbrush.fill")
                        .font(.largeTitle)
                        .padding()
                    VStack(alignment: .leading){
                    Text("All New User Interface")
                        .fontWeight(.bold)
                    Text ("Enhanced functionality....")
                    }
                }
            }
            }

        }.padding()

                Button("Dissmis") {
                    self.presentationMode.wrappedValue.dismiss()
                    }.padding()
                }
        }
}

And the ContentView my main View ....

The App Takes longer to load. Maybe it is because it is deleted and reinstalled.... It seems as if it is trying to load something but then after 5 to 7 sec the normal ContentView launches....

It writes out nothing, just as a normal launch.

Thanks in advance for taking your time.

3      

I did make a small app where i check after ContentView() has been started if the app is started for the first time. When you run the code right after the first start you will get a WhastNew screen. When you restart the app it won't appear until you change the version number of your app and start again.

Hope this helps.

In a production code i would move the two functions to an separate file/class for better readability of the code.

struct ContentView: View {

    // Variable to trigger WhatsNew Screen
    @State private var showWhatsNew = false

    // Get current Version of the App
    func getCurrentAppVersion() -> String {
        let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"]
        let version = (appVersion as! String)

        return version
    }

    // Check if app if app has been started after update
    func checkForUpdate() {
        let version = getCurrentAppVersion()
        let savedVersion = UserDefaults.standard.string(forKey: "savedVersion")

        if savedVersion == version {
            print("App is up to date!")
        } else {

            // Toogle to show WhatsNew Screen as Modal
            self.showWhatsNew.toggle()
            UserDefaults.standard.set(version, forKey: "savedVersion")
        }
    }

    var body: some View {

        return Text("Hello, World!")

            .sheet(isPresented: $showWhatsNew, content: { WhatsNew() }) // Show Sheet
            .onAppear(perform: checkForUpdate) // Run checkForUpdate when View Appears
    }
}
struct WhatsNew: View {

    // Variable to Dismiss Modal
    @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>

    var body: some View {

        return VStack {
            Text("Whats new in this version?")

            // Dismiss Button
            Button(action: { self.presentationMode.wrappedValue.dismiss() }, label: {
                Text("Dismiss")
            })
        }

    }
}

7      

Thank you very mutch it works perfect. The way you showed is way better solved than the Initial "How to tutorial" I was trying to implement.

4      

I have a Swift Package that is exactly for this purpose
CTWhatsNew_SwiftUI

5      

Hacking with Swift is sponsored by Essential Developer

SPONSORED Join a FREE crash course for mid/senior iOS devs who want to achieve an expert level of technical and practical skills – it’s the fast track to being a complete senior developer! Hurry up because it'll be available only until April 28th.

Click to save your free spot now

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.