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

时间:2014-02-19 11:01:50

标签: ios uuid uniqueidentifier identifier

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

我用

获得了identifierForVendor
NSString *uuid = [[UIDevice currentDevice] identifierForVendor].UUIDString

此标识符将存储在Web服务器的数据库中,也存储在设备数据库中。下一次当用户打开应用程序并尝试从Web服务器下载数据时,用户设备上的本地identifierForVendor将与存储在Web服务器上的标识符进行比较。 / p>

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

我阅读了苹果文档UIDevice Documentation

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

那么在我的情况下如何处理这个?

8 个答案:

答案 0 :(得分:63)

您可以将其保存在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 :(得分:19)

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

答案 2 :(得分:9)

除@ 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];

答案 3 :(得分:5)

您可以尝试使用 KeyChain 保存 VendorIdentifier ,即使您卸载了应用,该功能也会一直存在,直到您的设备重置为止。

答案 4 :(得分:4)

确定。我不想使用第三方 - 即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)]);
}

答案 5 :(得分:4)

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
}

答案 6 :(得分:2)

没有明确的方法可以将唯一号码与设备相关联,Apple隐私权准则不允许这样做。

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

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

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

答案 7 :(得分:0)

我曾使用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

在文件中导入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
    }