首页 文章

如何在设备上卸载ios app后保留ios中的identifierForVendor?

提问于
浏览
63

我正在开发一个iOS应用程序,它调用web服务进行登录,然后我将登录凭据与供应商标识符(identifierForVendor)一起发送到Web服务器,以便为这些凭证唯一地标识设备 . 因此用户只能拥有一个设备和一个凭证 .

我有了identifierForVendor

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

然后该标识符将存储在Web服务器的数据库中以及设备数据库中 . 当用户打开应用程序并尝试从Web服务器下载数据时,用户设备上的本地identifierForVendor将与存储在Web服务器上的标识符进行比较 .

用户卸载应用程序并重新安装时出现问题,我发现identifierForVendor已更改 . 因此用户无法继续前进 .

我读了苹果文档UIDevice Documentation

如前所述,如果来自同一供应商的所有应用程序都从设备卸载,则在从该供应商新安装任何应用程序时将采用新的identifierForVendor .

那么在我的案例中如何处理这个问题呢?

8 回答

  • 9

    您可以将其保存在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;
    }
    
  • 1

    一般情况下,请勿使用 identifierForVendor . 而是使用 NSUUID 生成自定义UUID并将其存储在钥匙串中(因为如果删除并重新安装应用程序,则不会删除钥匙串) .

  • 19

    除了@ nerowolfe的answer .

    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 ,即使您卸载了应用程序,也会一直存在,直到您的设备重置为止 .

  • 62

    好 . 我不想使用第三方 - 即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)]);
    }
    
  • 1

    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
    }
    
  • 4

    没有明确的方法可以将唯一号码链接到设备,Apple隐私准则不允许这样做 .

    您可以尝试在钥匙串中保存自己的唯一ID,但如果用户清除其设备,则此ID也会消失 .

    通常,link a device to a user是错误的,因为您不再识别用户而是设备 . 因此,您应该只更改API,以便用户可以重新登录,并且供应商ID绑定到用户帐户 .

    当用户拥有多个设备(如iPhone和iPad)并在两者上使用应用程序时会发生什么?由于您的身份验证基于唯一ID,因此无法执行此操作 .

  • 5

    我曾使用KeychainAccess pod来解决这个问题 .

    在您的pod文件中:

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

    在要在密钥链中设置UUID的文件中导入 KeychainAccess 模块

    import KeychainAccess
    

    使用以下代码设置并从钥匙串获取UUID:

    Note : 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
        }
    

相关问题