27

我需要检查我的应用程序何时启动是否正在更新,因为我需要创建一个仅在首次安装应用程序时出现的视图,以便在更新后再次出现。

4

8 回答 8

57

您可以保存一个值(例如当前应用程序版本号)NSUserDefaults并在每次用户启动应用程序时检查它。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // ...

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

    NSString *currentAppVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
    NSString *previousVersion = [defaults objectForKey:@"appVersion"];
    if (!previousVersion) {
        // first launch

        // ...

        [defaults setObject:currentAppVersion forKey:@"appVersion"];
        [defaults synchronize];
    } else if ([previousVersion isEqualToString:currentAppVersion]) {
        // same version
    } else {
        // other version

        // ...

        [defaults setObject:currentAppVersion forKey:@"appVersion"];
        [defaults synchronize];
    }



    return YES;
}

版本如下所示:

let defaults = NSUserDefaults.standardUserDefaults()

let currentAppVersion = NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleShortVersionString") as! String
let previousVersion = defaults.stringForKey("appVersion")
if previousVersion == nil {
    // first launch
    defaults.setObject(currentAppVersion, forKey: "appVersion")
    defaults.synchronize()
} else if previousVersion == currentAppVersion {
    // same version
} else {
    // other version
    defaults.setObject(currentAppVersion, forKey: "appVersion")
    defaults.synchronize()
}

版本如下所示:

let defaults = UserDefaults.standard

let currentAppVersion = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as! String
let previousVersion = defaults.string(forKey: "appVersion")
if previousVersion == nil {
    // first launch
    defaults.set(currentAppVersion, forKey: "appVersion")
    defaults.synchronize()
} else if previousVersion == currentAppVersion {
    // same version
} else {
    // other version
    defaults.set(currentAppVersion, forKey: "appVersion")
    defaults.synchronize()
}
于 2013-06-03T14:55:09.417 回答
8

您可以在 NSUserDefaults 中存储应用程序版本号,并在每次启动应用程序时检查它。如果该号码不可用,则为全新安装。如果它被改变,它是一个升级。

于 2013-06-03T14:49:37.900 回答
5

只需在应用启动时初始化 AppVersionUpdateNotifier 并符合 AppUpdateNotifier 协议,享受。

使用: 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
        }
    }
于 2017-09-25T18:18:45.847 回答
3

版本,对已接受的答案进行了重要改进:

  • 使用infoDictionary而不是objectForInfoDictionaryKey保证结果独立于设备语言,否则您可能会在极少数情况下最终认为有升级,而实际上它只是设备语言的更改
  • 使用与主 Bundle infoDictionary 相同的 UserDefaults 键,以清楚地了解确切存储的内容
  • 因式设置 currentVersion 代码
  • 斯威夫特 3 语法

代码:

    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()
    }
于 2017-03-02T09:54:27.507 回答
1

我认为,当你有一个小规模的应用程序时,给定的答案是好的,但是当你在一个具有很长路线图的大型 iOS 应用程序上工作时,你肯定需要一个强大的未来解决方案,并具有类似的好处。

  1. 更好地比较适用于所有可能性(2.0/2.0.0 等)的逻辑。
  2. 在迁移过程中采取特定操作,假设用户从 1.0 版本迁移到 2.0 和 1.1 到 2.0。
  3. 当用户重置应用程序(注销)时重置缓存版本。

下面是我在我的一个 iOS 应用程序中使用的代码片段。

public enum VersionConfigResponse {
    case freshInstalled
    case versionGreater
    case versionEqualOrLesser
    case currentVersionEmpty
}


/*
 Config manager responsible to handle the change needs to be done when user migrate from one Version to another Version.
 */
public class VersionConfig {

    public static let shared = VersionConfig()
    private init() { }
    private let versionKey = "SAVED_SHORT_VERSION_STRING"

    /*
     Cache the existing version for compare during next app launch.
     */
    private var storedVersion : String?  {
        get {
            return UserDefaults.standard.object(forKey: versionKey) as? String
        } set {
            UserDefaults.standard.set(newValue, forKey: versionKey)
            UserDefaults.standard.synchronize()
        }
    }

    /*
     Validate the current version with saved version, if greater do clean.
     */
    public func validate(currentVersion: String?) -> VersionConfigResponse  {
        guard let currentVersion = currentVersion else {
            return .currentVersionEmpty
        }

        guard let sVersion = storedVersion else {
            self.storedVersion = currentVersion
            self.freshInstalled()
            return .freshInstalled
        }

        if currentVersion.compare(sVersion, options: .numeric, range: nil, locale: nil) == .orderedDescending    {
            self.storedVersion = currentVersion
            self.userMigrated(fromVersion: sVersion, toVersion:currentVersion)
            return .versionGreater
        } else {
            return .versionEqualOrLesser
        }
    }

    private func userMigrated(fromVersion: String, toVersion: String)   {
        //take your action here...
    }

    private func freshInstalled()   {
        //take your action here...
    }

    /*
     Remove saved version if user reset(logout) the app.
     */
    public func reset() {
        self.storedVersion = nil
    }
}


//trigger version config with current version
VersionConfig.shared.validate(currentVersion: "1.0.0")

//reset when user logsout
VersionConfig.shared.reset()
于 2019-06-23T06:51:31.200 回答
1

这是一个简单的代码,用于了解当前版本是否不同(此代码也适用于模拟器。)

-(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;
}

注意:确保当您在 iTunes 中输入新版本时,该版本与您正在发布的应用程序中的版本相匹配。如果不是,那么无论用户是否更新,上述代码将始终返回 YES。

于 2017-10-31T13:02:06.750 回答
0

这对我有用..

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")
于 2020-11-16T15:11:32.253 回答
0

我创建了BundleInfoVersioningswift 包来帮助我解决这个问题。

它适用于信息字典中的所有键,例如CFBundleVersionorCFBundleShortVersionString和自定义键路径,例如NSAgora/DatabaseVersion.

例子:

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()
}

您可以在https://github.com/nsagora/bundle-info-versioning在 github 上查看。

于 2019-11-06T10:09:09.633 回答