Подтвердить что ты не робот

Как узнать, обновил ли пользователь приложение или установил новую копию?

Я отправлю обновление для своего приложения с новой структурой данных, поэтому, если пользователь обновляет мое приложение, мне нужно обновить их текущие данные. Поэтому мне было интересно, как я могу программно определить, обновил ли пользователь мое приложение или установил новую копию (если установлена ​​новая копия, мне не нужно ничего обновлять)?

4b9b3361

Ответ 1

Это зависит от типа используемой структуры данных.

В общем, я бы посоветовал вам не полагаться на проверку вашей версии приложения: пользователь, использующий 2.0, может просто обновиться или может быть новым пользователем.

Я бы предпочел проверить, есть ли уже структура данных и действовать соответственно. Предполагая, что вы используете хранилище Core Data с поддержкой Sqlite, вы можете проверить, существует ли файл .sqlite или проверить, есть ли в вашем хранилище объекты.

Ответ 2

Проверка структуры данных - это твердое решение. Я начал беспокоиться в своих приложениях о людях, которые не обновляют несколько версий. Я чувствовал, что это приведет к множеству структурных проверок. Код, показанный ниже, определяет и сохраняет версию и предыдущую версию в 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];
}

Ответ 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, "[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