identifierForVendor和iOS6是什么?

10

identifierForVendor需要iOS6及以上版本支持,因此如果我的应用程序目前支持iOS4,则由于我的更新应始终满足应用程序先前的最小要求,因此无法使用它。


请查看此线程:UniqueIdentifier现在导致苹果拒绝谢谢 - Ishara Meegahawala
5个回答

28

你可以使用以下代码:

NSString *udid;

if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"6.0"))
    udid = [UIDevice currentDevice].identifierForVendor.UUIDString;
else
    udid = [UIDevice currentDevice].uniqueIdentifier;

使用预处理器代码:

#define SYSTEM_VERSION_EQUAL_TO(v)                  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame)
#define SYSTEM_VERSION_GREATER_THAN(v)              ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN(v)                 ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v)     ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)

1
在else子句中,uniqueIdentifier在iOS5中已被弃用,因此请改用类似于随机UUID的东西。 代码:CFStringRef cfUuid = CFUUIDCreateString(NULL,CFUUIDCreate(NULL)); - malaba
11
而不是比较版本号,检查选择器:f([[UIDevice currentDevice] respondsToSelector:@selector(identifierForVendor)]) - malaba
然而,苹果不再批准使用“uniqueIdentifier”的应用程序。 - user102008
1
我们能在旧版iOS中使用uniqueIdentifier吗,就像他在回答中提到的那样?对于新版本的iOS,请使用identifierForVendor,对于旧版则使用uniqueIdentifier?这是否可行? - Arun Jose

7
你不需要使用预处理宏来实现此功能,你应该像这样检查它是否有响应:

(译者注:原句中的“response”可能是错别字或者笔误,正确的应该是“responds”)

if ([[UIDevice currentDevice]respondsToSelector:@selector(identifierForVendor)]) {
    return [UIDevice currentDevice].identifierForVendor.UUIDString;
}else{
    // return [UIDevice currentDevice]. uniqueIdentifier
    return [[UIDevice currentDevice] performSelector:@selector(uniqueIdentifier)];
}

2

这总是不同的。UUID包括时间戳,因此每次调用此函数时,您将获得一个不同的(随机)值。我在IDManager类中遵循了这种方法,这是来自不同解决方案的集合。KeyChainUtil是一个读取keychain的包装器。类似的keychain util可以在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

我在哪里可以获取KeychainUtil类/包装器? - DevCali

1
您可以使用以下代码。
if (NSClassFromString(@"ASIdentifierManager")) {
    return [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];           
} else {
    // return other identifier generated with OpenUDID or some custom method
}

您可以在这里获取OpenUDID文档。


0

看一下NSSelectorFromString和[NSObject performSelector:SEL]。 NSSelectorFromString允许您通过字符串在运行时选择一个选择器。在运行时与操作系统版本检查结合使用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接