I need to check when my app launches if it was being updated, because i need to make a view that only appears when the app is firstly installed to appear again after being
I've created BundleInfoVersioning swift package to help me solve this issue.
It works with all keys in the info dictionary, like CFBundleVersion
or CFBundleShortVersionString
and with custom key paths like, for example, NSAgora/DatabaseVersion
.
Examples:
let bundleInfoVersioning = BundleInfoVersioning(bundle: .main)
bundleInfoVersioning.check(forKeyPath: "CFBundleVersion") { (old: String?, new: String?) in
if old == nil {
Analytics.install(version: new)
}
else {
Analytics.update(from: old, to: new)
}
}
bundleInfoVersioning.check(forKeyPath: "CFBundleShortVersionString") { _ , newVersion in
self.showWhatsNew(in: newVersion)
}
bundleInfoVersioning.check(forKeyPath: "NSAgora/DatabaseVersion") { (old: Int?, new: Int?) in
self.resetDataBase()
}
You can check it out on github at https://github.com/nsagora/bundle-info-versioning.
Here is a simple code to know if the current version is different (this code work on simulator too.)
-(BOOL) needsUpdate
{
NSDictionary* infoDictionary = [[NSBundle mainBundle] infoDictionary];
NSString* appID = infoDictionary[@"CFBundleIdentifier"];
NSURL* url = [NSURL URLWithString:[NSString stringWithFormat:@"http://itunes.apple.com/lookup?bundleId=%@", appID]];
NSData* data = [NSData dataWithContentsOfURL:url];
NSDictionary* lookup = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
if ([lookup[@"resultCount"] integerValue] == 1)
{
NSString* appStoreVersion = lookup[@"results"][0][@"version"];
NSString* currentVersion = infoDictionary[@"CFBundleShortVersionString"];
if (![appStoreVersion isEqualToString:currentVersion])
{
NSLog(@"Need to update [%@ != %@]", appStoreVersion, currentVersion);
return YES;
}
}
return NO;
}
Note: Make sure that when you enter the new version in iTunes, this matches the version in the app you are releasing. If not then the above code will always return YES regardless if the user updates.
This worked for me..
func compareVersion(old:String,latest:String) -> Bool {
if latest.compare(old, options: .numeric) == .orderedDescending {
return true
}
return false
}
compareVersion(old: "3.1.5", latest: "3.2")
you can store a app version number in NSUserDefaults and check it every time your app is launched. If the number is not available, its a fresh installation. If it is changed , it is an upgrade.
swift version with an important improvement over the accepted answer:
infoDictionary
instead of objectForInfoDictionaryKey
guaranties that the result is independent from device language, otherwise you may end up in some rare cases believing that there is an upgrade when in reality it is just a device language changeCode:
let standardUserDefaults = UserDefaults.standard
let shortVersionKey = "CFBundleShortVersionString"
let currentVersion = Bundle.main.infoDictionary![shortVersionKey] as! String
let previousVersion = standardUserDefaults.object(forKey: shortVersionKey) as? String
if previousVersion == currentVersion {
// same version
} else {
// replace with `if let previousVersion = previousVersion {` if you need the exact value
if previousVersion != nil {
// new version
} else {
// first launch
}
standardUserDefaults.set(currentVersion, forKey: shortVersionKey)
standardUserDefaults.synchronize()
}
Just initialise AppVersionUpdateNotifier in app launch and conform AppUpdateNotifier protocol, enjoy.
Use: Swift 3.x
extension AppDelegate: AppUpdateNotifier {
func onVersionUpdate(newVersion: Int, oldVersion: Int) {
// do something
}
func onFirstLaunch() {
//do something
}
}
class AppVersionUpdateNotifier {
static let KEY_APP_VERSION = "key_app_version"
static let shared = AppVersionUpdateNotifier()
private let userDefault:UserDefaults
private var delegate:AppUpdateNotifier?
private init() {
self.userDefault = UserDefaults.standard
}
func initNotifier(_ delegate:AppUpdateNotifier) {
self.delegate = delegate
checkVersionAndNotify()
}
private func checkVersionAndNotify() {
let versionOfLastRun = userDefault.object(forKey: AppVersionUpdateNotifier.KEY_APP_VERSION) as? Int
let currentVersion = Int(Bundle.main.buildVersion)!
if versionOfLastRun == nil {
// First start after installing the app
delegate?.onFirstLaunch()
} else if versionOfLastRun != currentVersion {
// App was updated since last run
delegate?.onVersionUpdate(newVersion: currentVersion, oldVersion: versionOfLastRun!)
} else {
// nothing changed
}
userDefault.set(currentVersion, forKey: AppVersionUpdateNotifier.KEY_APP_VERSION)
}
}
protocol AppUpdateNotifier {
func onFirstLaunch()
func onVersionUpdate(newVersion:Int, oldVersion:Int)
}
extension Bundle {
var shortVersion: String {
return infoDictionary!["CFBundleShortVersionString"] as! String
}
var buildVersion: String {
return infoDictionary!["CFBundleVersion"] as! String
}
}