with - Actualización de la base de datos sqlite cuando la versión de la aplicación cambia en Appstore en iPhone
sqlite with swift 4 (3)
Tengo una aplicación con la versión 1.0 en la tienda de aplicaciones que utiliza la base de datos sqlite para leer los datos.
Ahora quiero actualizar mi versión a 1.1 con la actualización en el archivo de base de datos.
Al utilizar el certificado de desarrollador cuando instalo la aplicación en el dispositivo, no actualizó la base de datos, ya que el archivo de la base de datos ya existe en la carpeta de documentos, así que tengo que eliminar manualmente la aplicación e instalarla de nuevo.
Mi pregunta es, cuando cualquier usuario actualice la aplicación, la base de datos también se actualizará de acuerdo con la versión actual.
Cualquier sugerencia es bienvenida.
Gracias
Este enfoque se basa en NSUserDefaults
. La idea es obtener el número de versión de la aplicación anterior (si existe) de NSUserDefaults
y compararla con la versión actual.
El código realiza la actualización de la base de datos si la versión de la aplicación anterior <
a la versión actual o si la versión anterior es nil
. Esto significa que este enfoque se puede utilizar aunque la aplicación ya se haya publicado en la AppStore. Actualizará la base de datos a la nueva versión durante la actualización de la aplicación.
Este es un archivo plist:
Existe una matriz compuesta por el número de versión y un conjunto de consultas de SQL para la versión de actualización correspondiente. Supongamos que una versión anterior es 1.2 y la versión real es 1.4, el código realiza la actualización solo de la versión 1.2 a 1.4. Si la versión anterior es 1.3 y la versión 1.4 actual, el código realiza la actualización solo de 1.3 a 1.4. Si la versión anterior es nula, el código realiza una actualización a 1.1, luego a 1.2, luego a 1.3 y finalmente a 1.4.
NSString * const VERSION_KEY = @"version";
-(void)upgradeDatabaseIfRequired{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *previousVersion=[defaults objectForKey:VERSION_KEY];
NSString *currentVersion=[self versionNumberString];
if (previousVersion==nil || [previousVersion compare: currentVersion options: NSNumericSearch] == NSOrderedAscending) {
// previous < current
//read upgrade sqls from file
NSString *plistPath = [[NSBundle mainBundle] pathForResource:@"UpgradeDatabase" ofType:@"plist"];
NSArray *plist = [NSArray arrayWithContentsOfFile:plistPath];
if (previousVersion==nil) {//perform all upgrades
for (NSDictionary *dictionary in plist) {
NSString *version=[dictionary objectForKey:@"version"];
NSLog(@"Upgrading to v. %@", version);
NSArray *sqlQueries=[dictionary objectForKey:@"sql"];
while (![DB executeMultipleSql:sqlQueries]) {
NSLog(@"Failed to upgrade database to v. %@, Retrying...", version);
};
}
}else{
for (NSDictionary *dictionary in plist) {
NSString *version=[dictionary objectForKey:@"version"];
if ([previousVersion compare: version options: NSNumericSearch] == NSOrderedAscending) {
//previous < version
NSLog(@"Upgrading to v. %@", version);
NSArray *sqlQueries=[dictionary objectForKey:@"sql"];
while (![DB executeMultipleSql:sqlQueries]) {
NSLog(@"Failed to upgrade database to v. %@, Retrying...", version);
};
}
}
}
[defaults setObject:currentVersion forKey:VERSION_KEY];
[defaults synchronize];
}
}
- (NSString *)versionNumberString {
NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];
NSString *majorVersion = [infoDictionary objectForKey:@"CFBundleShortVersionString"];
return majorVersion;
}
Estoy seguro de que hay muchas maneras de hacer esto (y de muchas otras maneras, también las mías), pero la forma en que manejo estos problemas es la siguiente:
Primero, defino una constante en el primer archivo .h de la aplicación (el que se cargará primero) para indicar la carga por primera vez y establecerla en 0:
#define FirstTime 0
Ahora debe saber que tengo la intención de guardar el valor de esta constante en la carpeta Documentos para futuras referencias, por lo tanto, uso una instancia de datos compartidos. En el viewDidLoad
hago la siguiente prueba:
//if first time run of this version
if( [MyDataModel sharedInstance].count < (FirstTime + 1) )
{
//do what you need to do as the first time load for this version
[MyDataModel sharedInstance].count++
//save the count value to disk so on next run you are not first time
//this means count = 1
}
Ahora el truco está en su nueva versión de la aplicación (digamos 1.1). Cambio el FirstTime
a 2:
#define FirstTime 2
Dado que el valor de la primera vez guardado en el disco es 1, esto significa que la instrucción if que se encuentra arriba lo atrapará, por lo tanto, dentro de él, puede hacer lo que quiera, eliminar las tablas antiguas y volver a crearlas con la nueva formación.
¡Otra vez no tan brillante, pero resuelve el caso!
Puedes usar .plist
también:
- (void)isItTheFirstTimeAfterUpdate {
NSString *versionnum;
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask,
YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:@"yourplist.plist"];
NSFileManager *fileManager = [NSFileManager defaultManager];
if(![fileManager fileExistsAtPath:path]) {
NSString *bundle = [[NSBundle mainBundle] pathForResource:@"yourplist" ofType:@"plist"];
[fileManager copyItemAtPath:bundle toPath:path error:&error];
}
NSMutableDictionary *savedStock = [[NSMutableDictionary alloc] initWithContentsOfFile:path];
versionnum = @"";
//it can be installed by user (for ex. it is 1.3 but first installed), no plist value is set before
if(([savedStock objectForKey:@"versionnum"]) && (![[savedStock objectForKey:@"versionnum"] isEqualToString:@""])){
versionnum = [savedStock objectForKey:@"versionnum"];
}
//to get the version of installed/updated-current app
NSString *myversion = [NSString stringWithFormat:@"%@",[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"]];
//if no version has been set-first install- or my version is the latest version no need to do sth.
if ([versionnum isEqualToString:myversion] || [versionnum isEqualToString:@""]) {
NSLog(@"Nothing has to be done");
}
else {
[self cleanDB];//i have clean tables and create my new db tables maybe logout the user etc.
[savedStock setObject:[NSString stringWithString:myversion] forKey:@"versionnum"];//setting the new version
[savedStock writeToFile:path atomically:YES];
}
}
Y puede llamar a la función en el inicio de la aplicación o en el controlador de vista de su controlador de vista principal ... su elección.
Espero eso ayude.