2011-05-17 10 views
12

Enviaré una actualización de mi aplicación con una nueva estructura de datos, por lo tanto, si un usuario está actualizando mi aplicación, necesito actualizar sus datos actuales. Entonces me preguntaba cómo puedo saber programáticamente si el usuario actualizó mi aplicación o instaló una nueva copia (si hay una nueva copia instalada, no necesito actualizar nada).¿Cómo saber si el usuario ha actualizado la aplicación o ha instalado una copia nueva?

+0

¿Qué estructura de datos 'está usando? Datos básicos? – magma

Respuesta

7

Eso depende del tipo de estructura de datos que esté utilizando.

En general, te aconsejaría no depender de la comprobación de su versión de la aplicación: un usuario utilizando 2,0 podría haber acaba de actualizar o que podría ser un nuevo usuario.

Prefiero comprobar si ya hay una estructura de datos, y actuar en consecuencia. Asumiendo que está usando un almacenamiento de Datos Core respaldado por Sqlite, puede verificar si el archivo .sqlite existe o verificar si hay objetos en su almacenamiento.

+1

¡Casi respondía lo mismo! – Saurabh

+0

En realidad estoy usando una lista de propiedades, pero creo que puedo verificar si faltan datos o algo, gracias. – cgossain

+2

Ignora mi respuesta. No entiendo bien tu pregunta. +1 para esta respuesta. –

3

Sólo tiene que guardar la versión del paquete en algún lugar y comprobar si se diferencia de

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

en cada inicio de aplicaciones.

7

Verificar la estructura de datos es una solución sólida. Empecé a preocuparme en mis propias aplicaciones sobre personas que no actualizan para varias versiones. Sentí que esto llevaría a una miríada de controles de estructura. El código que muestro a continuación determina y almacena la versión y la versión anterior en el NSUserDefaults. Podría codificar los diferentes escenarios de diferencias de versión si fuera necesario.

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

Gracias por las ediciones: @Edward Falk – dredful

+0

Gracias por las ediciones: @Matt Carrier – dredful

0

He creado una categoría para esto. Simplemente implemente las dos nuevas llamadas de delegado encontradas en el encabezado. Se basa bastante en las bibliotecas de tiempo de ejecución obj-c, así que asegúrese de tener confianza con ellos antes de usar esto.

.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 
Cuestiones relacionadas