【问题标题】:Check if my IOS application is updated检查我的 IOS 应用程序是否已更新
【发布时间】:2013-05-29 18:24:33
【问题描述】:

如果我的应用程序正在更新,我需要检查它何时启动,因为我需要 使仅在首次安装应用程序时出现的视图在安装后再次出现 更新了。

【问题讨论】:

  • 这个问题你需要详细说明一下:更新了什么?应用程序本身或应用程序内的文件或要从远程服务器下载的文件?
  • 应用本身正在更新中

标签: ios objective-c swift uiapplication


【解决方案1】:

只需在应用启动时初始化 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
        }
    }

【讨论】:

  • 太好了...谢谢。
【解决方案2】:

这对我有用..

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")

【讨论】:

    【解决方案3】:

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

    它适用于信息字典中的所有键,例如 CFBundleVersion 或 CFBundleShortVersionString,以及自定义键路径,例如 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上查看它。

    【讨论】:

      【解决方案4】:

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

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

      下面是我在我的一个 iOS 应用程序中使用的代码 sn-p。

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

      【讨论】:

        【解决方案5】:

        您可以将一个值(例如当前应用程序版本号)保存到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()
        }
        

        【讨论】:

        • 我们如何检查是否已经发布的应用程序不支持上述机制?
        • @damithH 如果您发布的应用程序使用 NSUserDefaults,那么只需检查您使用的任何密钥是否存在。
        • Apple 文档说 synchronize() 等待对默认数据库的任何挂起的异步更新并返回;这种方法是不必要的,不应该使用。 Synchronize
        【解决方案6】:

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

        -(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。

        【讨论】:

        【解决方案7】:

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

        • 使用infoDictionary 而不是objectForInfoDictionaryKey 可以保证结果独立于设备语言,否则在极少数情况下您可能最终会认为有升级,而实际上它只是设备语言更改
        • 使用与主 Bundle infoDictionary 相同的 UserDefaults 键,以明确存储的内容
        • 分解设置 currentVersion 代码
        • Swift 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()
            }
        

        【讨论】:

          【解决方案8】:

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

          【讨论】:

          • 我读到更新后 NSUserDefaults 不会被删除,所以这对我没有帮助,如果用户先删除应用程序并重新安装它,这将起作用
          • @user2412870 将您的版本号存储在 NSUserDefaults 中并检查,如果更新,您可以检查版本号是否与 NSUserDefaults 中保存的数字相似
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多