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

Как сохранить идентификаторForVendor в ios после удаления приложения ios на устройстве?

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

Я получил идентификатор ForVendor с

NSString *uuid = [[UIDevice currentDevice] identifierForVendor].UUIDString

Этот идентификатор будет храниться в базе данных веб-сервера, а также в базе данных устройства. В следующий раз, когда пользователь откроет приложение и попытается загрузить данные с веб-сервера, сначала локальный идентификаторForVendor на устройстве пользователя будет сравниваться с идентификатором, хранящимся на веб-сервере.

Проблема возникает, когда пользователь удаляет приложение и переустанавливает его, я обнаружил, что идентификаторForVendor изменен. Поэтому пользователь не может продолжить.

Я прочитал документацию по яблоко Документация UIDevice

Как упоминается там, если все приложения от одного и того же поставщика удаляются с устройства, то в момент новой установки любого приложения от этого поставщика возьмет новый идентификаторForVendor.

Итак, как справиться с этим в моем случае?

4b9b3361

Ответ 1

Вы можете сохранить его в 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;
}

Ответ 2

Как правило, не используйте identifierForVendor. Вместо этого используйте NSUUID для создания пользовательского UUID и сохраните его в цепочке ключей (поскольку цепочка ключей не удаляется, если приложение удалено и переустановлено).

Ответ 3

Дополнение к @nerowolfe ответ.

SSKeychain использует kSecAttrSynchronizableAny как режим синхронизации по умолчанию. Вероятно, вы не хотите, чтобы identifierForVendor синхронизировался на нескольких устройствах, поэтому вот код:

// 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];

Ответ 4

Вы можете использовать KeyChain, чтобы сохранить VendorIdentifier, который будет существовать до вашего устройства reset, даже если вы удалите свое приложение.

Ответ 5

Ok. Я не хотел использовать третью сторону, а именно SSKeychain. Так что это код, который я пробовал, довольно простой и хорошо работает:

    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)]);
}

Ответ 6

Быстрая версия

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
}

Ответ 7

Нет никакого определенного способа связать уникальный номер с устройством, это запрещено в соответствии с правилами конфиденциальности Apple.

Вы можете попытаться сохранить свой собственный уникальный идентификатор в цепочке ключей, но если пользователь очистит его устройство, этот идентификатор также исчезнет.

Как правило, неправильно связывать устройство с пользователем, поскольку вы больше не идентифицируете пользователей, а устройства. Поэтому вы должны просто изменить свой API, чтобы пользователь мог повторно войти в систему и что идентификатор поставщика привязан к учетной записи пользователя.

Также, когда пользователь имеет более одного устройства, например iPhone и iPad, и использует ваше приложение для обоих? Поскольку аутентификация основана на уникальном идентификаторе, это невозможно.

Ответ 8

Я использовал KeychainAccess для этой проблемы.

В вашем файле подкачки:

pod 'KeychainAccess', '~> 2.4' //If you are using Swift 2.3 
pod 'KeychainAccess' //Defaults to 3.0.1 which is in Swift 3

Импортировать модуль KeychainAccess в файл, где вы хотите установить UUID в цепочке ключей

import KeychainAccess

Используйте код ниже, чтобы установить и получить UUID из брелка:

Примечание: BundleId является ключом, а UUID - значением

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
    }