2011-05-17 45 views
12

我將用新的數據結構向我的應用程序發送更新,因此如果用戶正在更新我的應用程序,我需要更新其當前數據。所以我想知道如何以編程方式告訴用戶是否更新了我的應用程序或安裝了新的副本(如果安裝了新副本,我不需要更新任何內容)?如何知道用戶是否已更新應用程序或安裝了新的副本?

+0

什麼 '數據結構' 您使用的?核心數據? – magma 2011-05-17 17:31:54

回答

7

這取決於您使用的數據結構的類型。

一般來說,我建議你不要依靠檢查你的應用程序版本:使用2.0的用戶可能剛剛升級它可能是一個新用戶。

我寧願檢查是否已經有數據結構,並採取相應的行動。假設您使用的是Sqlite支持的Core Data存儲,您可以檢查.sqlite文件是否存在,或者檢查存儲中是否有對象。

+1

我幾乎回答同樣的問題! – Saurabh 2011-05-17 17:36:08

+0

我實際上使用了一個屬性列表,但我想我可以檢查丟失的數據或者其他感謝。 – cgossain 2011-05-17 17:39:08

+2

忽略我的答案。我誤解了你的問題。 +1這個答案。 – 2011-05-17 18:04:19

3

只是保存在某個地方的捆綁版本,並檢查它是否從

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

不同,每個應用程序的啓動。

7

檢查數據結構是一個可靠的解決方案。我開始擔心在我自己的應用程序中關於不升級幾個版本的人。我覺得這會導致無數的結構檢查。我在下面顯示的代碼確定並存儲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]; 
} 
+0

感謝您的編輯:@Edward Falk – dredful 2013-04-30 00:12:46

+0

感謝您的編輯:@Matt Carrier – dredful 2013-04-30 00:13:41

0

我爲此創建了一個類別。只需實現標題中找到的兩個新的委託調用即可。它非常依賴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, "[email protected]:@@"); 

    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 
相關問題