【问题标题】:identifierForVendor and iOS6identifierForVendor 和 iOS6
【发布时间】:2012-09-12 11:32:42
【问题描述】:

identifierForVendor 需要 iOS6,因此如果我的应用当前支持 iOS4,因此我无法使用它,因为我的更新应该始终满足我应用之前的最低要求。要求?

【问题讨论】:

标签: objective-c ios xcode itunes


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    您可以使用以下代码

    if (NSClassFromString(@"ASIdentifierManager")) {
        return [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];           
    } else {
        // return other identifier generated with OpenUDID or some custom method
    }
    

    您可以获取 OpenUDID 文档here

    【讨论】:

      【解决方案3】:

      你可以用这个:

      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)
      

      【讨论】:

      • 在 else 子句中,uniqueIdentifier 在 iOS5 中已被弃用,因此请改用随机 UUID 的方式。代码:CFStringRef cfUuid = CFUUIDCreateString(NULL, CFUUIDCreate(NULL));
      • 不是比较版本,而是检查选择器:f ([[UIDevice currentDevice] respondsToSelector:@selector(identifierForVendor)])
      • 但是,Apple 不再批准使用 uniqueIdentifier 的应用程序
      • 我们可以将 uniqueIdentifier 用于旧的 ios 版本,就像他在回答中提到的那样?对于新的 ios 版本,使用 identifierForVendor 和旧的 uniqueIdentifier???这可能吗?
      【解决方案4】:

      它总是不同的。 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
      

      【讨论】:

      • 我在哪里可以获得 KeychainUtil 类/包装器?
      【解决方案5】:

      你不需要预处理宏,你应该检查它是否响应,像这样:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-05-16
        • 2017-02-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多