【问题标题】:How to know if user has updated app or installed a fresh copy?如何知道用户是否更新了应用程序或安装了新副本?
【发布时间】:2011-05-17 17:27:24
【问题描述】:

我将使用新的数据结构向我的应用发送更新,因此如果用户正在更新我的应用,我需要更新他们当前的数据。所以我想知道如何以编程方式判断用户是否更新了我的应用程序或安装了新副本(如果安装了新副本,我不需要更新任何内容)?

【问题讨论】:

  • 您使用的是什么“数据结构”?核心数据?

标签: iphone ios4 iphone-sdk-3.0


【解决方案1】:

检查数据结构是一个可靠的解决方案。我开始在我自己的应用程序中担心那些不升级多个版本的人。我觉得这会导致无数的结构检查。我在下面显示的代码确定版本和以前的版本并将其存储在NSUserDefaults 中。如果需要,您可以为这些不同的版本差异场景编写代码。

NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
BOOL versionUpgraded;
NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];
NSString *preVersion = [prefs stringForKey:@"appVersion"];

if ([prefs stringForKey:@"appVersion"] != nil) {
    //see if version is the same as prior
    //if not it is an Upgraded
    versionUpgraded = !([preVersion isEqualToString: version]);
} else {
    //nil means new install
            //This needs to be YES for the case that
            //"appVersion" is not set anywhere else.
    versionUpgraded = YES; 
}

if (versionUpgraded) {
    [prefs setObject:version forKey:@"appVersion"];
    [prefs setObject:preVersion forKey:@"prevAppVersion"];

    [prefs synchronize];
}

【讨论】:

    【解决方案2】:

    这取决于您使用的数据结构类型。

    一般来说,我建议您不要依赖检查您的应用程序版本:使用 2.0 的用户可能刚刚升级它可能是新用户。

    我宁愿检查是否已经存在数据结构,并采取相应措施。假设您使用的是 Sqlite 支持的 Core Data 存储,您可以检查 .sqlite 文件是否存在,或者检查存储中是否存在对象。

    【讨论】:

    • 我的回答几乎一样!
    • 我实际上正在使用属性列表,但我想我可以检查丢失的数据或其他东西,谢谢。
    • 忽略我的回答。我误解了你的问题。对此答案 +1。
    【解决方案3】:

    只需将捆绑版本保存在某处并检查它是否与

    [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]]

    在每次应用启动时。

    【讨论】:

      【解决方案4】:

      我为此创建了一个类别。只需实现在标头中找到的两个新委托调用。它非常依赖 obj-c 运行时库,因此在使用它之前请确保您对它们有信心。

      .h

      #import <UIKit/UIKit.h>
      
      @protocol UIApplicationDelegate <UIApplicationDelegate>
      @optional
      - (void) application:(UIApplication *)application willUpdateToVersion: (NSString*) newVersion fromVersion: (NSString*) previousVersion;
      - (void) application:(UIApplication *)application didUpdateToVersion: (NSString*) newVersion fromVersion: (NSString*) previousVersion;
      
      @end
      
      @interface UIApplication (Versioning)
      
      @end
      

      .m

      #import "UIApplication+Versioning.h"
      
      #import <objc/message.h>
      #import <objc/runtime.h>
      
      static NSString* UIApplicationVersionFileName = @"app.ver";
      
      @implementation UIApplication (Versioning)
      
      + (void) load {
          Method original, swizzled;
      
          original = class_getInstanceMethod(self, @selector(setDelegate:));
          swizzled = class_getInstanceMethod(self, @selector(swizzled_setDelegate:));
      
          method_exchangeImplementations(original, swizzled);
      }
      
      - (void) swizzled_setDelegate: (id<UIApplicationDelegate>) delegate {
      
          IMP implementation = class_getMethodImplementation([self class], @selector(swizzled_application:didFinishLaunchingWithOptions:));
          class_addMethod([delegate class], @selector(swizzled_application:didFinishLaunchingWithOptions:), implementation, "B@:@@");
      
          Method original, swizzled;
      
          original = class_getInstanceMethod([delegate class], @selector(application:didFinishLaunchingWithOptions:));
          swizzled = class_getInstanceMethod([delegate class], @selector(swizzled_application:didFinishLaunchingWithOptions:));
      
          method_exchangeImplementations(original, swizzled);
      
          [self swizzled_setDelegate: delegate];
      }
      
      - (BOOL)swizzled_application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
      
          //Check for a version change
          NSError* error;
          NSArray* directories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
          NSString* versionFilePath = [[directories objectAtIndex: 0] stringByAppendingPathComponent: UIApplicationVersionFileName];
          NSString* oldVersion = [NSString stringWithContentsOfFile: versionFilePath
                                                           encoding: NSUTF8StringEncoding
                                                              error: &error];
          NSString* currentVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey: @"CFBundleVersion"];
      
          switch (error.code) {
              case NSFileReadNoSuchFileError:
              {
                  //Delegate methods will not be called first time
                  oldVersion = [currentVersion copy];
                  [currentVersion writeToFile: versionFilePath
                                   atomically: YES
                                     encoding: NSUTF8StringEncoding
                                        error: &error];
                  break;
              }
              default:
              {
                  NSLog(@"Warning: An error occured will loading the application version file -> Recreating file");
                  [[NSFileManager defaultManager] removeItemAtPath: versionFilePath
                                                             error: nil];
                  oldVersion = [currentVersion copy];
                  [currentVersion writeToFile: versionFilePath
                                   atomically: YES
                                     encoding: NSUTF8StringEncoding
                                        error: &error];
                  break;
              }
          }
      
          if( ![oldVersion isEqualToString: currentVersion] ) {
      
              if ([[application delegate] respondsToSelector: @selector(application:willUpdateToVersion:fromVersion:)]) {
                  objc_msgSend([application delegate], @selector(application:willUpdateToVersion:fromVersion:), currentVersion, oldVersion);
              }
      
              [currentVersion writeToFile: versionFilePath
                               atomically: YES
                                 encoding: NSUTF8StringEncoding
                                    error: &error];
      
              if ([[application delegate] respondsToSelector: @selector(application:didUpdateToVersion:fromVersion:)]) {
                  objc_msgSend([application delegate], @selector(application:willUpdateToVersion:fromVersion:), currentVersion, oldVersion);
              }
      
          }
      
          SEL realSelector =  @selector(swizzled_application:didFinishLaunchingWithOptions:);
          return (BOOL) objc_msgSend([application delegate], realSelector, application, launchOptions);
      }
      
      @end
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-09-20
        • 2016-11-27
        • 2020-11-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多