ios - que - instale una app y no la puedo desinstalar
¿Cómo conservar identifierForVendor en iOS después de desinstalar la aplicación ios en el dispositivo? (8)
Estoy desarrollando una aplicación iOS que llama al servicio web para iniciar sesión y en ese momento envío credenciales de inicio de sesión al servidor web junto con el identificador del proveedor (identifierForVendor), para identificar el dispositivo de manera exclusiva para esas credenciales. Por lo tanto, el usuario puede tener un solo dispositivo y una credencial .
Obtuve identifierForVendor con
NSString *uuid = [[UIDevice currentDevice] identifierForVendor].UUIDString
Este identificador se almacenará en la base de datos del servidor web y también en la base de datos del dispositivo. La próxima vez que el usuario abra la aplicación intentará descargar datos del servidor web. En primer lugar, el identificador localForVendor en el dispositivo de los usuarios se comparará con el identificador almacenado en el servidor web.
El problema ocurre cuando el usuario desinstala la aplicación y la vuelve a instalar, encontré que identifierForVendor ha cambiado. Entonces el usuario no puede continuar.
Leí la documentación de apple UIDevice Documentation
Como mencionamos allí, si todas las aplicaciones del mismo proveedor se desinstalan del dispositivo, en el momento de la nueva instalación de cualquier aplicación de ese proveedor se tomará el nuevo identificador ForVendor.
Entonces, ¿cómo lidiar con esto en mi caso?
Además de la answer de @nerowolfe.
SSKeychain usa kSecAttrSynchronizableAny
como modo de sincronización predeterminado. Probablemente no desee que identifierForVendor
se sincronice en varios dispositivos, así que aquí hay un código:
// save identifierForVendor in keychain without sync
NSError *error = nil;
SSKeychainQuery *query = [[SSKeychainQuery alloc] init];
query.service = @"your_service";
query.account = @"your_account";
query.password = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
query.synchronizationMode = SSKeychainQuerySynchronizationModeNo;
[query save:&error];
De acuerdo. No quería utilizar un tercero, a saber, SSKeychain. Este es el código que probé, bastante simple y funciona bien:
NSString *bundleId = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIdentifier"];
KeychainItemWrapper *keychainItem = [[KeychainItemWrapper alloc] initWithIdentifier:bundleId accessGroup:nil];
if(![keychainItem objectForKey:(__bridge id)(kSecValueData)]){
NSString *idfa = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
[keychainItem setObject:idfa forKey:(__bridge id)(kSecValueData)];
NSLog(@"saving item %@", [keychainItem objectForKey:(__bridge id)(kSecValueData)]);
}else{
NSLog(@"saved item is %@", [keychainItem objectForKey:(__bridge id)(kSecValueData)]);
}
En general, no use identifierForVendor
. En su lugar, use NSUUID
para generar un UUID personalizado y almacénelo en el llavero (porque el llavero no se elimina si la aplicación se elimina y vuelve a instalar).
Había usado el pod de KeychainAccess para este problema.
En tu archivo pod:
pod ''KeychainAccess'', ''~> 2.4'' //If you are using Swift 2.3
pod ''KeychainAccess'' //Defaults to 3.0.1 which is in Swift 3
Importe el módulo KeychainAccess
en el archivo donde desea establecer el UUID en el llavero
import KeychainAccess
Use el código siguiente para establecer y obtener UUID de keychain:
Nota: BundleId es clave y UUID es valor
var bundleID = NSBundle.mainBundle().bundleIdentifier
var uuidValue = UIDevice.currentDevice().identifierForVendor!.UUIDString
//MARK: - setVenderId and getVenderId
func setVenderId() {
let keychain = Keychain(service: bundleID!)
do {
try keychain.set(venderId as String, key: bundleID!)
print("venderId set : key /(bundleID) and value: /(venderId)")
}
catch let error {
print("Could not save data in Keychain : /(error)")
}
}
func getVenderId() -> String {
let keychain = Keychain(service: bundleID!)
let token : String = try! keychain.get(bundleID!)!
return token
}
No hay una manera definida de vincular un número único a un dispositivo, esto no está permitido con las pautas de privacidad de Apple.
Puede intentar guardar su propia identificación única en el llavero, pero si el usuario borra su dispositivo, esta identificación también desaparecerá.
En general, es simplemente incorrecto vincular un dispositivo a un usuario , ya que ya no identifica usuarios sino dispositivos. Por lo tanto, solo debe cambiar su API para que el usuario pueda volver a iniciar sesión y que la identificación del proveedor esté vinculada a la cuenta de los usuarios.
Además, ¿qué sucede cuando el usuario tiene más de un dispositivo, como un iPhone y iPad, y usa su aplicación en ambos? Como su autenticación se basa en una identificación única, esto no se puede hacer.
Puede intentar utilizar KeyChain para guardar su VendorIdentifier , que existirá hasta que se restablezca su dispositivo, incluso si desinstala su aplicación.
Puede mantenerlo en KeyChain
-(NSString *)getUniqueDeviceIdentifierAsString
{
NSString *appName=[[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey];
NSString *strApplicationUUID = [SSKeychain passwordForService:appName account:@"incoding"];
if (strApplicationUUID == nil)
{
strApplicationUUID = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
[SSKeychain setPassword:strApplicationUUID forService:appName account:@"incoding"];
}
return strApplicationUUID;
}
Versión Swift
func UUID() -> String {
let bundleName = NSBundle.mainBundle().infoDictionary!["CFBundleName"] as! String
let accountName = "incoding"
var applicationUUID = SAMKeychain.passwordForService(bundleName, account: accountName)
if applicationUUID == nil {
applicationUUID = UIDevice.currentDevice().identifierForVendor!.UUIDString
// Save applicationUUID in keychain without synchronization
let query = SAMKeychainQuery()
query.service = bundleName
query.account = accountName
query.password = applicationUUID
query.synchronizationMode = SAMKeychainQuerySynchronizationMode.No
do {
try query.save()
} catch let error as NSError {
print("SAMKeychainQuery Exception: /(error)")
}
}
return applicationUUID
}