I have a requirement of detecting the first launch of app after the user upgrades the app to a newer version. I need to perform certain task only on first launch of app after the user upgrades the app to a new version. Many links available online but none answer clearly to my query. How to achieve this in Swift 2 , iOS 9.
Most of the answers available says to maintain a key in NSUserDefaults and set its value to false and after first launch make it true. But the problem is after I upgrade my app the variable still will be true and thus my scenario fails on app upgrade. Any help would be much appreciated. Thanks!
Try this:
let existingVersion = NSUserDefaults.standardUserDefaults().objectForKey("CurrentVersionNumber") as? String
let appVersionNumber = NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleShortVersionString") as! String
if existingVersion != appVersionNumber {
NSUserDefaults.standardUserDefaults().setObject(appVersionNumber, forKey: "CurrentVersionNumber")
NSUserDefaults.standardUserDefaults().synchronize()
//You can handle your code here
}
updating Yogesh's perfect, yet simple solution to swift 4
let existingVersion = UserDefaults.standard.object(forKey: "CurrentVersionNumber") as? String
let appVersionNumber = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as! String
if existingVersion != appVersionNumber {
print("existingVersion = \(String(describing: existingVersion))")
UserDefaults.standard.set(appVersionNumber, forKey: "CurrentVersionNumber")
// run code here.
}
Related
Hi I am learning by watching the video. Since it was an old version, it seemed that you were using NS, but I don’t know how to use it now, so I ask
Youtube video link
https://www.youtube.com/watch?v=PKOswUE731c >> 32:40
let userEmailStored = NSUserDefaults.standardUserDefaults().stringForKey("userEmail")
let userPasswordStored = NSUserDefulats.standardUserDefaults().stringForKey("userPassword")
In the current version, we know that you should use it without NS, but it is not used even if you subtract NS.
Cannot be used
I would appreciate it if you let me know.
You can use UserDefaults now and get the String values like this:
let userEmailStored = UserDefaults.standard.string(forKey: "userEmail")
let userPasswordStored = UserDefaults.standard.string(forKey: "userPassword")
You can use UserDefaults now and set the String values like this:
UserDefaults.standard.set("email", forKey: "userEmail")
UserDefaults.standard.set("password", forKey: "userPassword")
I am storing information about meal timing in Apple's Health App/DB. When I review Apples Health App for meal information (top screen in the image) the source App Icon is included in the list.
When I attempt to do the same in my App (Bottom Screen in the image) it works fine for my Apps BundleID but I cannot retrieve the App Icon from the Health App supplied BundleID for an alternate source App. I am using the code shown below to try to achieve this. I am not sure what I am doing wrong, perhaps the wrong approach, perhaps missing some setup calls (like opening the Bundle before use). I have seen this used in third-party fitness/nutrition apps so there must be some way for doing this. I would appreciate any help or redirection of my effort. Thanks in advance.
func getAppIcon(_ theBundleID: String) -> UIImage {
guard let iconsDictionary = Bundle.init(identifier: theBundleID)!.infoDictionary?["CFBundleIcons"] as? NSDictionary,
let primaryIconsDictionary = iconsDictionary["CFBundlePrimaryIcon"] as? NSDictionary,
let iconFiles = primaryIconsDictionary["CFBundleIconFiles"] as? [String],
// First will be smallest for the device class, last will be the largest for device class
let firstIcon = iconFiles.first,
let icon = UIImage(named: firstIcon as String) else {
return UIImage()
}
return icon
}
I've developed a game and I released it to the App Store about 2 months ago (Supernatural Slayer). The game uses user defaults to store player data such as level, xp, gold, etc.
I want to update the game to include review requests which I programmed based on help from hacking with swift. (I also had to switch ad networks since chart boost suspended my account indefinitely for no reason...)
My question is that I seem to remember during development about 4-6 months ago that every time I added another variable to save and load from user defaults it would cause an existing game to crash and I would have to start from scratch by deleting and reloading the game onto my phone to erase user defaults. But now that I'm adding the reviewRequest variable it isn't causing the same error, I'm not sure if I'm not testing correctly and if once I update all of my players will lose their progress...
My code for the save and load functions is below, will this cause an error for existing users that update my app if I add the reviewRequest variable and the save and load lines for it? I've updated both my Mac OS and Xcode since it used to crash for me, so maybe this is why it is not an issue anymore?
let defaults = UserDefaults.standard
var reviewRequest = 0
func save() {
defaults.set(reviewRequest, forKey: "Review Request")
defaults.set(player.name, forKey: "PlayerName")
}
func load() {
player.name = defaults.object(forKey: "PlayerName") as! String
reviewRequest = defaults.integer(forKey: "Review Request")
}
You should try adding a nil check to avoid trying to retrieve an empty key.
func load() {
if defaults.object(forKey: "PlayerName") != nil {
player.name = defaults.object(forKey: "PlayerName") as! String
} else {
//Default name or something similar
}
if defaults.object(forKey: "ReviewRequest") != nil {
reviewRequest = defaults.integer(forKey: "Review Request")
} else {
reviewRequest = 0
}
}
Im a beginner in Swift 3.0. Recently i just convert existing swift project to 3.0 swift. After converrted, i have issues storing user& password using key chain wrapper.
i have checked the result of Bool, it just show false and the value is nil.
Can i know the possible causes? thanks for guiding.
//This is how i store
var saveSuccessful:Bool = KeychainWrapper.defaultKeychainWrapper().setString(txt_userId.text!, forKey: "userId")
let savePass:Bool = KeychainWrapper.setString(txt_password.text!, forKey: "password")
//this is how i get/retrieve
var password:String? = KeychainWrapper.stringForKey("password")
Take a look at my answer here. The problem is that the "Keychain Sharing" capability has to be enabled.
This question already has answers here:
Check if my IOS application is updated
(8 answers)
Closed 5 years ago.
I am developing an application and i need to know whether user installed the app for the first time or upgraded it from the App Store.
How can i detect whether app is installed for the first time or upgraded or re-installed?
Thanks for your answers in advance.
You can differentiate between the first start after installing the App, the first start after an update and other starts quite easily via saving the latest known version to standardUserDefaults. But as far as I know it is not possible do detect a re-install of the App as all App-related data are also removed when the App is deleted from the device.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSString* currentVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:#"CFBundleVersion"];
NSString* versionOfLastRun = [[NSUserDefaults standardUserDefaults] objectForKey:#"VersionOfLastRun"];
if (versionOfLastRun == nil) {
// First start after installing the app
} else if (![versionOfLastRun isEqual:currentVersion]) {
// App was updated since last run
} else {
// nothing changed
}
[[NSUserDefaults standardUserDefaults] setObject:currentVersion forKey:#"VersionOfLastRun"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
Checkout Swift 3.0 version of code.
Note: Use CFBundleShortVersionString, for checking actual App version checking.
func checkAppUpgrade() {
let currentVersion = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String
let versionOfLastRun = UserDefaults.standard.object(forKey: "VersionOfLastRun") as? String
if versionOfLastRun == nil {
// First start after installing the app
} else if versionOfLastRun != currentVersion {
// App was updated since last run
} else {
// nothing changed
}
UserDefaults.standard.set(currentVersion, forKey: "VersionOfLastRun")
UserDefaults.standard.synchronize()
}
For Swift 3
let currentVersion : String = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as! String
let versionOfLastRun: String? = UserDefaults.standard.object(forKey: "VersionOfLastRun") as? String
if versionOfLastRun == nil {
// First start after installing the app
} else if !(versionOfLastRun?.isEqual(currentVersion))! {
// App is updated
}
UserDefaults.standard.set(currentVersion, forKey: "VersionOfLastRun")
UserDefaults.standard.synchronize()
Just for note:
To obtain localized value of any key you should use CFBundleGetValueForInfoDictionaryKey(CFBundleGetMainBundle(), "CFBundleShortVersionString" as CFString)
Please store a version in NSUserDefaults (per #Nero's answer) for checking (possible) fresh installs and subsequent updates.
For checking reinstalls (in the case where stored version == nil), exploit iOS 11's introduction of DeviceCheck API which exposes two bits of device specific data which can be set and retrieved by the app, but maintained by Apple and persisted across an uninstall/reinstalls.