2

我想使用 UDID 的替代方法并发现:

+ (NSString *)GetUUID
{
  CFUUIDRef theUUID = CFUUIDCreate(NULL);
  CFStringRef string = CFUUIDCreateString(NULL, theUUID);
  CFRelease(theUUID);
  return [(NSString *)string autorelease];
}

但是在模拟器中,该方法每次会话都会给我不同的结果?

这仅在模拟器中吗?

我需要确保在实际设备上,该方法总是返回相同的字符串来识别用户。

这是真的还是假的?

米尔扎

4

6 回答 6

1

CFUUIDRef将在每个会话中创建不同的值。

解决方案1:

保存该值,NSUserDefaults下次从NSUserDefaults使用它。

解决方案2:

你可以 identifierForVendor用来做这个。

NSString *udidVendor = [[[UIDevice currentDevice] identifierForVendor] UUIDString];

根据UIDevice 类参考

对于来自同一供应商并在同一设备上运行的应用,此属性的值相同。对于来自不同供应商的同一设备上的应用程序以及不同设备上的应用程序(无论供应商)返回不同的值。

请检查iOS 6 中的唯一标识符

于 2013-05-23T12:02:39.560 回答
1

每次调用该函数时,CFUUIDCreate 都会为您提供一个通用唯一标识符,因此每次您都会得到不同的结果(根据定义)。

您可以做的是在会话之间使用例如 NSUserDefaults 来保持它,以唯一地标识特定用户(或一组用户设置)。

于 2013-05-23T10:35:11.333 回答
0

该方法将始终返回一个唯一的字符串。如果应用程序只有一个用户,请在用户首次启动应用程序时运行一次此方法,并将该字符串保存在 plist、NSUserDefaults 或核心数据中(如果您已经使用它)。

下面的链接可能有助于此 UUID 持久性逻辑: UUID for app on iOS5

但是,如果用户随后卸载并重新安装应用程序,这个持久化的 UUID 仍然会丢失,并且会再次生成需求。

Apple 也不再允许使用设备 ID。

假设由于应用程序连接到服务器而需要 UUID,据我所知,您需要用户使用用户名和密码登录服务器。

于 2013-05-23T10:49:35.767 回答
0

CFUUID 根本不持久。

每次调用 CFUUIDCreate 时,系统都会返回一个全新的唯一标识符。

如果你想保留这个标识符,你需要自己使用 NSUserDefaults、Keychain、Pasteboard 或其他方式来完成。

于 2013-05-23T10:35:06.397 回答
0

一次读一行代码,试着理解它的作用。每次调用该CFUUIDCreate函数都会创建一个新的 UUID。这可以解释你的发现。您需要在NSUserDefaults第一次保存 * 中的值并在下次启动应用程序时使用该值:

+ (NSString *)GetUUID
{
    NSString *string = [[NSUserDefaults standardUserDefaults] objectForKey: @"UUID"];
    if (!string)
    {
        CFUUIDRef theUUID = CFUUIDCreate(NULL);
        string = (NSString*)[CFUUIDCreateString(NULL, theUUID) autorelease];
        CFRelease(theUUID);
        [[NSUserDefaults standardUserDefaults] setObject: string forKey: @"UUID"];
    }
    return string;
}

*使用时有一个小注意事项NSUserDefaults- 如果用户卸载并重新安装应用程序,将再次创建 UUID。如果您不能忍受这个,请考虑将其保存在钥匙串中。或者,您可能想查看OpenUDID

于 2013-05-23T10:36:33.917 回答
0

它总是不同的。UUID 包含时间戳,因此每次调用此函数时,都会得到一个不同的(随机)。我在IDManager课堂上遵循了这种方法,这是来自不同解决方案的集合。KeyChainUtil 是一个从钥匙串中读取的包装器。在github中可以找到类似的钥匙串工具。

//  IDManager.m


/*
 A replacement for deprecated uniqueIdentifier API. Apple restrict using this from 1st May, 2013.

 We have to consider,
    * iOS <6 have not the ASIIdentifer API
    * When the user upgrade from iOS < 6 to >6
        - Check if there is a UUID already stored in keychain. Then use that. 
            - In that case, this UUID is constant for whole device lifetime. Keychain item is not deleted with application deletion.
 */

#import "IDManager.h"
#import "KeychainUtils.h"
#import "CommonUtil.h"

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 60000
    #import <AdSupport/AdSupport.h>
#endif

#include <sys/socket.h> 
#include <sys/sysctl.h>
#include <net/if.h>
#include <net/if_dl.h>



/*  Apple confirmed this bug in their system in response to a Technical Support Incident request. They said that identifierForVendor and advertisingIdentifier sometimes returning all zeros can be seen both in development builds and apps downloaded over the air from the App Store. They have no work around and can't say when the problem will be fixed. */
#define kBuggyASIID             @"00000000-0000-0000-0000-000000000000"


#pragma mark 


#pragma mark 

@implementation IDManager

+ (NSString *) getUniqueID {

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 60000

    if (NSClassFromString(@"ASIdentifierManager")) {
        NSString * asiID = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
        if ([asiID compare:kBuggyASIID] == NSOrderedSame) {
            NSLog(@"Error: This device return buggy advertisingIdentifier.");
            return [IDManager getUniqueUUID];
        } else {
            return asiID;
        }

    } else {

#endif

        return [IDManager getUniqueUUID];

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 60000
    }
#endif

}

+ (NSString *) getUniqueUUID 
{
    NSError * error;
    NSString * uuid = [KeychainUtils getPasswordForUsername:@"UserName" andServiceName:@"YourServiceName" error:&error];
    if (error) {
        NSLog(@"Error geting unique UUID for this device! %@", [error localizedDescription]);
        return nil;
    }
    if (!uuid) {
        DLog(@"No UUID found. Creating a new one.");
        uuid = [IDManager getUUID];
        uuid = [CommonUtil md5String:uuid]; // create md5 hash for security reason
        [KeychainUtils storeUsername:@"UserName" andPassword:uuid forServiceName:@"YourServiceName" updateExisting:YES error:&error];
        if (error) {
            NSLog(@"Error geting unique UUID for this device! %@", [error localizedDescription]);
            return nil;
        }
    }
    return uuid;
}

+ (NSString *) readUUIDFromKeyChain {
    NSError * error;
    NSString * uuid = [KeychainUtils getPasswordForUsername:@"UserName" andServiceName:@"YourServiceName" error:&error];
    if (error) {
        NSLog(@"Error geting unique UUID for this device! %@", [error localizedDescription]);
        return nil;
    }
    return uuid;
}

/* NSUUID is after iOS 6. So we are using CFUUID for compatibility with iOS 4.3 */
+ (NSString *)getUUID
{
    CFUUIDRef theUUID = CFUUIDCreate(NULL);
    CFStringRef string = CFUUIDCreateString(NULL, theUUID);
    CFRelease(theUUID);
    return [(NSString *)string autorelease];
}

#pragma mark - MAC address

/* THIS WILL NOT WORK IN iOS 7. IT WILL RETURN A CONSTANT MAC ADDRESS ALL THE TIME.
 SEE - https://developer.apple.com/news/?id=8222013a
 */

// Return the local MAC address
// Courtesy of FreeBSD hackers email list
// Last fallback for unique identifier
+ (NSString *) getMACAddress
{
    int                 mib[6];
    size_t              len;
    char                *buf;
    unsigned char       *ptr;
    struct if_msghdr    *ifm;
    struct sockaddr_dl  *sdl;

    mib[0] = CTL_NET;
    mib[1] = AF_ROUTE;
    mib[2] = 0;
    mib[3] = AF_LINK;
    mib[4] = NET_RT_IFLIST;

    if ((mib[5] = if_nametoindex("en0")) == 0) {
        printf("Error: if_nametoindex error\n");
        return NULL;
    }

    if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) {
        printf("Error: sysctl, take 1\n");
        return NULL;
    }

    if ((buf = malloc(len)) == NULL) {
        printf("Error: Memory allocation error\n");
        return NULL;
    }

    if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
        printf("Error: sysctl, take 2\n");
        free(buf); // Thanks, Remy "Psy" Demerest
        return NULL;
    }

    ifm = (struct if_msghdr *)buf;
    sdl = (struct sockaddr_dl *)(ifm + 1);
    ptr = (unsigned char *)LLADDR(sdl);
    NSString *outstring = [NSString stringWithFormat:@"%02X:%02X:%02X:%02X:%02X:%02X",
                           *ptr, *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4), *(ptr+5)];

    free(buf);
    return outstring;
}

+ (NSString *) getHashedMACAddress
{
    NSString * mac = [IDManager getMACAddress];
    return [CommonUtil md5String:mac];
}

@end
于 2013-05-23T10:37:28.237 回答