├── README.md ├── UIDevice+VKKeychainIDFV.h ├── UIDevice+VKKeychainIDFV.m └── VKKeychainIDFV_proj ├── VKKeychainIDFV_proj.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── Awhisper.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── Awhisper.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ ├── VKKeychainIDFV_proj.xcscheme │ └── xcschememanagement.plist └── VKKeychainIDFV_proj ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets └── AppIcon.appiconset │ └── Contents.json ├── Base.lproj ├── LaunchScreen.storyboard └── Main.storyboard ├── Info.plist ├── ViewController.h ├── ViewController.m └── main.m /README.md: -------------------------------------------------------------------------------- 1 | 2 | 没啥技术含量,把工作里的老用的东西,单拿出来了,留个念想 3 | 4 | # VKKeychainIDFV 5 | 6 | 开发中都有获取uuid`用户唯一标示`的需求 7 | 8 | 有很多种方法 9 | idfv是苹果后来提供的用于识别设备唯一标识的方案之一(注意__之一__) 10 | 11 | 12 | - IMEI,苹果允许的API不能获取,不会变化,设备唯一 13 | - UDID,曾经可以获取现在也成为禁止调用的API,不会变化,设备唯一, 14 | - MAC,不能直接通过设备API获取,某种脑洞可以通过WIFI下路由器反馈信息来回传MAC地址,很不方便,不会变化,设备唯一 15 | - IDFA,广告标示符,经常容易变,每当用户针对app关闭再开启一次广告追踪,就会发生变化 16 | - IDFV,厂商标示符,不太容易变,每当用户卸载完app厂家旗下所有app后,再次安装,会发生变化 17 | - NSUUID,苹果API接口,每次获取都变化 18 | 19 | 可以确认的是,在众多可选的标识方案里,都不能保证永远不变,所以必须配合Keychain使用,有了keychain至少保证,只要用户不刷机,无论是升级系统,还是卸载光所有app,都不会发生变化 20 | 21 | 只要有了Keychain的辅助,可以说随便选一个标识,只要存入keychain,都能保证不变了。 22 | 23 | 这里选择了目前来看更加稳定的IDFV 24 | 25 | 26 | # Usage 27 | 28 | 导入文件 29 | 30 | `import "UIDevice+VKKeychainIDFV.h"` 31 | 32 | `NSString* idfv = [UIDevice VKKeychainIDFV];` 33 | -------------------------------------------------------------------------------- /UIDevice+VKKeychainIDFV.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIDevice+VKKeychainIDFV.h 3 | // VKKeychainIDFV 4 | // 5 | // Created by Awhisper on 16/5/9. 6 | // Copyright © 2016年 baidu. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIDevice (VKKeychainIDFV) 12 | 13 | -(NSString *)VKKeychainIDFV; 14 | 15 | +(NSString *)VKKeychainIDFV; 16 | 17 | -(void)removeVKKeychainIDFV; 18 | 19 | +(void)removeVKKeychainIDFV; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /UIDevice+VKKeychainIDFV.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIDevice+VKKeychainIDFV.m 3 | // VKKeychainIDFV 4 | // 5 | // Created by Awhisper on 16/5/9. 6 | // Copyright © 2016年 baidu. All rights reserved. 7 | // 8 | 9 | #import "UIDevice+VKKeychainIDFV.h" 10 | 11 | @implementation UIDevice (VKKeychainIDFV) 12 | 13 | +(NSString *)VKKeychainIDFV 14 | { 15 | return [[self currentDevice] VKKeychainIDFV]; 16 | } 17 | 18 | -(NSString *)VKKeychainIDFV 19 | { 20 | NSString *idfv = [self VKgetIdfvFromKeyChain]; 21 | 22 | if (idfv && idfv.length > 0 && [idfv isKindOfClass:[NSString class]]) { 23 | return idfv; 24 | }else 25 | { 26 | NSString *idfv = [[self identifierForVendor] UUIDString]; 27 | idfv = [idfv stringByReplacingOccurrencesOfString:@"-" withString:@""]; 28 | [self VKsaveIdfvToKeyChain:idfv]; 29 | return idfv; 30 | } 31 | } 32 | 33 | 34 | -(void)removeVKKeychainIDFV 35 | { 36 | NSString *keychainKey = [[NSBundle mainBundle] bundleIdentifier]; 37 | keychainKey = [keychainKey stringByAppendingString:@".VKIDFV"]; 38 | [self VKdelete:keychainKey]; 39 | } 40 | 41 | +(void)removeVKKeychainIDFV 42 | { 43 | [[self currentDevice] removeVKKeychainIDFV]; 44 | } 45 | 46 | 47 | -(void)VKsaveIdfvToKeyChain:(NSString *)idfv 48 | { 49 | NSString *keychainKey = [[NSBundle mainBundle] bundleIdentifier]; 50 | keychainKey = [keychainKey stringByAppendingString:@".VKIDFV"]; 51 | [self VKsave:keychainKey data:idfv]; 52 | } 53 | 54 | -(NSString *)VKgetIdfvFromKeyChain 55 | { 56 | NSString *keychainKey = [[NSBundle mainBundle] bundleIdentifier]; 57 | keychainKey = [keychainKey stringByAppendingString:@".VKIDFV"]; 58 | NSString * idfv = [self load:keychainKey]; 59 | return idfv; 60 | } 61 | 62 | 63 | - (NSMutableDictionary *)VKgetKeychainQuery:(NSString *)service { 64 | return [NSMutableDictionary dictionaryWithObjectsAndKeys: 65 | (__bridge_transfer id)kSecClassGenericPassword,(__bridge_transfer id)kSecClass, 66 | service, (__bridge_transfer id)kSecAttrService, 67 | service, (__bridge_transfer id)kSecAttrAccount, 68 | (__bridge_transfer id)kSecAttrAccessibleAfterFirstUnlock,(__bridge_transfer id)kSecAttrAccessible, 69 | nil]; 70 | } 71 | 72 | - (void)VKsave:(NSString *)service data:(id)data { 73 | //Get search dictionary 74 | NSMutableDictionary *keychainQuery = [self VKgetKeychainQuery:service]; 75 | //Delete old item before add new item 76 | SecItemDelete((__bridge_retained CFDictionaryRef)keychainQuery); 77 | //Add new object to search dictionary(Attention:the data format) 78 | [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(__bridge_transfer id)kSecValueData]; 79 | //Add item to keychain with the search dictionary 80 | SecItemAdd((__bridge_retained CFDictionaryRef)keychainQuery, NULL); 81 | } 82 | 83 | - (id)load:(NSString *)service { 84 | id ret = nil; 85 | NSMutableDictionary *keychainQuery = [self VKgetKeychainQuery:service]; 86 | //Configure the search setting 87 | [keychainQuery setObject:(id)kCFBooleanTrue forKey:(__bridge_transfer id)kSecReturnData]; 88 | [keychainQuery setObject:(__bridge_transfer id)kSecMatchLimitOne forKey:(__bridge_transfer id)kSecMatchLimit]; 89 | CFDataRef keyData = NULL; 90 | if (SecItemCopyMatching((__bridge_retained CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyData) == noErr) { 91 | @try { 92 | ret = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge_transfer NSData *)keyData]; 93 | } @catch (NSException *e) { 94 | NSLog(@"Unarchive of %@ failed: %@", service, e); 95 | } @finally { 96 | } 97 | } 98 | return ret; 99 | } 100 | 101 | - (void)VKdelete:(NSString *)service { 102 | NSMutableDictionary *keychainQuery = [self VKgetKeychainQuery:service]; 103 | SecItemDelete((__bridge_retained CFDictionaryRef)keychainQuery); 104 | } 105 | @end 106 | -------------------------------------------------------------------------------- /VKKeychainIDFV_proj/VKKeychainIDFV_proj.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 6C181A731CE0A6E7003852A1 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C181A721CE0A6E7003852A1 /* main.m */; }; 11 | 6C181A761CE0A6E7003852A1 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C181A751CE0A6E7003852A1 /* AppDelegate.m */; }; 12 | 6C181A791CE0A6E7003852A1 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C181A781CE0A6E7003852A1 /* ViewController.m */; }; 13 | 6C181A7C1CE0A6E7003852A1 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6C181A7A1CE0A6E7003852A1 /* Main.storyboard */; }; 14 | 6C181A7E1CE0A6E7003852A1 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6C181A7D1CE0A6E7003852A1 /* Assets.xcassets */; }; 15 | 6C181A811CE0A6E7003852A1 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6C181A7F1CE0A6E7003852A1 /* LaunchScreen.storyboard */; }; 16 | 6C181A8A1CE0A6F5003852A1 /* UIDevice+VKKeychainIDFV.m in Sources */ = {isa = PBXBuildFile; fileRef = 6C181A891CE0A6F5003852A1 /* UIDevice+VKKeychainIDFV.m */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXFileReference section */ 20 | 6C181A6E1CE0A6E7003852A1 /* VKKeychainIDFV_proj.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = VKKeychainIDFV_proj.app; sourceTree = BUILT_PRODUCTS_DIR; }; 21 | 6C181A721CE0A6E7003852A1 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 22 | 6C181A741CE0A6E7003852A1 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 23 | 6C181A751CE0A6E7003852A1 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 24 | 6C181A771CE0A6E7003852A1 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 25 | 6C181A781CE0A6E7003852A1 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 26 | 6C181A7B1CE0A6E7003852A1 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 27 | 6C181A7D1CE0A6E7003852A1 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 28 | 6C181A801CE0A6E7003852A1 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 29 | 6C181A821CE0A6E7003852A1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 30 | 6C181A881CE0A6F5003852A1 /* UIDevice+VKKeychainIDFV.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIDevice+VKKeychainIDFV.h"; path = "../UIDevice+VKKeychainIDFV.h"; sourceTree = ""; }; 31 | 6C181A891CE0A6F5003852A1 /* UIDevice+VKKeychainIDFV.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UIDevice+VKKeychainIDFV.m"; path = "../UIDevice+VKKeychainIDFV.m"; sourceTree = ""; }; 32 | /* End PBXFileReference section */ 33 | 34 | /* Begin PBXFrameworksBuildPhase section */ 35 | 6C181A6B1CE0A6E7003852A1 /* Frameworks */ = { 36 | isa = PBXFrameworksBuildPhase; 37 | buildActionMask = 2147483647; 38 | files = ( 39 | ); 40 | runOnlyForDeploymentPostprocessing = 0; 41 | }; 42 | /* End PBXFrameworksBuildPhase section */ 43 | 44 | /* Begin PBXGroup section */ 45 | 6C181A651CE0A6E7003852A1 = { 46 | isa = PBXGroup; 47 | children = ( 48 | 6C181A881CE0A6F5003852A1 /* UIDevice+VKKeychainIDFV.h */, 49 | 6C181A891CE0A6F5003852A1 /* UIDevice+VKKeychainIDFV.m */, 50 | 6C181A701CE0A6E7003852A1 /* VKKeychainIDFV_proj */, 51 | 6C181A6F1CE0A6E7003852A1 /* Products */, 52 | ); 53 | sourceTree = ""; 54 | }; 55 | 6C181A6F1CE0A6E7003852A1 /* Products */ = { 56 | isa = PBXGroup; 57 | children = ( 58 | 6C181A6E1CE0A6E7003852A1 /* VKKeychainIDFV_proj.app */, 59 | ); 60 | name = Products; 61 | sourceTree = ""; 62 | }; 63 | 6C181A701CE0A6E7003852A1 /* VKKeychainIDFV_proj */ = { 64 | isa = PBXGroup; 65 | children = ( 66 | 6C181A741CE0A6E7003852A1 /* AppDelegate.h */, 67 | 6C181A751CE0A6E7003852A1 /* AppDelegate.m */, 68 | 6C181A771CE0A6E7003852A1 /* ViewController.h */, 69 | 6C181A781CE0A6E7003852A1 /* ViewController.m */, 70 | 6C181A7A1CE0A6E7003852A1 /* Main.storyboard */, 71 | 6C181A7D1CE0A6E7003852A1 /* Assets.xcassets */, 72 | 6C181A7F1CE0A6E7003852A1 /* LaunchScreen.storyboard */, 73 | 6C181A821CE0A6E7003852A1 /* Info.plist */, 74 | 6C181A711CE0A6E7003852A1 /* Supporting Files */, 75 | ); 76 | path = VKKeychainIDFV_proj; 77 | sourceTree = ""; 78 | }; 79 | 6C181A711CE0A6E7003852A1 /* Supporting Files */ = { 80 | isa = PBXGroup; 81 | children = ( 82 | 6C181A721CE0A6E7003852A1 /* main.m */, 83 | ); 84 | name = "Supporting Files"; 85 | sourceTree = ""; 86 | }; 87 | /* End PBXGroup section */ 88 | 89 | /* Begin PBXNativeTarget section */ 90 | 6C181A6D1CE0A6E7003852A1 /* VKKeychainIDFV_proj */ = { 91 | isa = PBXNativeTarget; 92 | buildConfigurationList = 6C181A851CE0A6E7003852A1 /* Build configuration list for PBXNativeTarget "VKKeychainIDFV_proj" */; 93 | buildPhases = ( 94 | 6C181A6A1CE0A6E7003852A1 /* Sources */, 95 | 6C181A6B1CE0A6E7003852A1 /* Frameworks */, 96 | 6C181A6C1CE0A6E7003852A1 /* Resources */, 97 | ); 98 | buildRules = ( 99 | ); 100 | dependencies = ( 101 | ); 102 | name = VKKeychainIDFV_proj; 103 | productName = VKKeychainIDFV_proj; 104 | productReference = 6C181A6E1CE0A6E7003852A1 /* VKKeychainIDFV_proj.app */; 105 | productType = "com.apple.product-type.application"; 106 | }; 107 | /* End PBXNativeTarget section */ 108 | 109 | /* Begin PBXProject section */ 110 | 6C181A661CE0A6E7003852A1 /* Project object */ = { 111 | isa = PBXProject; 112 | attributes = { 113 | LastUpgradeCheck = 0720; 114 | ORGANIZATIONNAME = baidu; 115 | TargetAttributes = { 116 | 6C181A6D1CE0A6E7003852A1 = { 117 | CreatedOnToolsVersion = 7.2.1; 118 | }; 119 | }; 120 | }; 121 | buildConfigurationList = 6C181A691CE0A6E7003852A1 /* Build configuration list for PBXProject "VKKeychainIDFV_proj" */; 122 | compatibilityVersion = "Xcode 3.2"; 123 | developmentRegion = English; 124 | hasScannedForEncodings = 0; 125 | knownRegions = ( 126 | en, 127 | Base, 128 | ); 129 | mainGroup = 6C181A651CE0A6E7003852A1; 130 | productRefGroup = 6C181A6F1CE0A6E7003852A1 /* Products */; 131 | projectDirPath = ""; 132 | projectRoot = ""; 133 | targets = ( 134 | 6C181A6D1CE0A6E7003852A1 /* VKKeychainIDFV_proj */, 135 | ); 136 | }; 137 | /* End PBXProject section */ 138 | 139 | /* Begin PBXResourcesBuildPhase section */ 140 | 6C181A6C1CE0A6E7003852A1 /* Resources */ = { 141 | isa = PBXResourcesBuildPhase; 142 | buildActionMask = 2147483647; 143 | files = ( 144 | 6C181A811CE0A6E7003852A1 /* LaunchScreen.storyboard in Resources */, 145 | 6C181A7E1CE0A6E7003852A1 /* Assets.xcassets in Resources */, 146 | 6C181A7C1CE0A6E7003852A1 /* Main.storyboard in Resources */, 147 | ); 148 | runOnlyForDeploymentPostprocessing = 0; 149 | }; 150 | /* End PBXResourcesBuildPhase section */ 151 | 152 | /* Begin PBXSourcesBuildPhase section */ 153 | 6C181A6A1CE0A6E7003852A1 /* Sources */ = { 154 | isa = PBXSourcesBuildPhase; 155 | buildActionMask = 2147483647; 156 | files = ( 157 | 6C181A791CE0A6E7003852A1 /* ViewController.m in Sources */, 158 | 6C181A761CE0A6E7003852A1 /* AppDelegate.m in Sources */, 159 | 6C181A731CE0A6E7003852A1 /* main.m in Sources */, 160 | 6C181A8A1CE0A6F5003852A1 /* UIDevice+VKKeychainIDFV.m in Sources */, 161 | ); 162 | runOnlyForDeploymentPostprocessing = 0; 163 | }; 164 | /* End PBXSourcesBuildPhase section */ 165 | 166 | /* Begin PBXVariantGroup section */ 167 | 6C181A7A1CE0A6E7003852A1 /* Main.storyboard */ = { 168 | isa = PBXVariantGroup; 169 | children = ( 170 | 6C181A7B1CE0A6E7003852A1 /* Base */, 171 | ); 172 | name = Main.storyboard; 173 | sourceTree = ""; 174 | }; 175 | 6C181A7F1CE0A6E7003852A1 /* LaunchScreen.storyboard */ = { 176 | isa = PBXVariantGroup; 177 | children = ( 178 | 6C181A801CE0A6E7003852A1 /* Base */, 179 | ); 180 | name = LaunchScreen.storyboard; 181 | sourceTree = ""; 182 | }; 183 | /* End PBXVariantGroup section */ 184 | 185 | /* Begin XCBuildConfiguration section */ 186 | 6C181A831CE0A6E7003852A1 /* Debug */ = { 187 | isa = XCBuildConfiguration; 188 | buildSettings = { 189 | ALWAYS_SEARCH_USER_PATHS = NO; 190 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 191 | CLANG_CXX_LIBRARY = "libc++"; 192 | CLANG_ENABLE_MODULES = YES; 193 | CLANG_ENABLE_OBJC_ARC = YES; 194 | CLANG_WARN_BOOL_CONVERSION = YES; 195 | CLANG_WARN_CONSTANT_CONVERSION = YES; 196 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 197 | CLANG_WARN_EMPTY_BODY = YES; 198 | CLANG_WARN_ENUM_CONVERSION = YES; 199 | CLANG_WARN_INT_CONVERSION = YES; 200 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 201 | CLANG_WARN_UNREACHABLE_CODE = YES; 202 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 203 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 204 | COPY_PHASE_STRIP = NO; 205 | DEBUG_INFORMATION_FORMAT = dwarf; 206 | ENABLE_STRICT_OBJC_MSGSEND = YES; 207 | ENABLE_TESTABILITY = YES; 208 | GCC_C_LANGUAGE_STANDARD = gnu99; 209 | GCC_DYNAMIC_NO_PIC = NO; 210 | GCC_NO_COMMON_BLOCKS = YES; 211 | GCC_OPTIMIZATION_LEVEL = 0; 212 | GCC_PREPROCESSOR_DEFINITIONS = ( 213 | "DEBUG=1", 214 | "$(inherited)", 215 | ); 216 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 217 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 218 | GCC_WARN_UNDECLARED_SELECTOR = YES; 219 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 220 | GCC_WARN_UNUSED_FUNCTION = YES; 221 | GCC_WARN_UNUSED_VARIABLE = YES; 222 | IPHONEOS_DEPLOYMENT_TARGET = 9.2; 223 | MTL_ENABLE_DEBUG_INFO = YES; 224 | ONLY_ACTIVE_ARCH = YES; 225 | SDKROOT = iphoneos; 226 | TARGETED_DEVICE_FAMILY = "1,2"; 227 | }; 228 | name = Debug; 229 | }; 230 | 6C181A841CE0A6E7003852A1 /* Release */ = { 231 | isa = XCBuildConfiguration; 232 | buildSettings = { 233 | ALWAYS_SEARCH_USER_PATHS = NO; 234 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 235 | CLANG_CXX_LIBRARY = "libc++"; 236 | CLANG_ENABLE_MODULES = YES; 237 | CLANG_ENABLE_OBJC_ARC = YES; 238 | CLANG_WARN_BOOL_CONVERSION = YES; 239 | CLANG_WARN_CONSTANT_CONVERSION = YES; 240 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 241 | CLANG_WARN_EMPTY_BODY = YES; 242 | CLANG_WARN_ENUM_CONVERSION = YES; 243 | CLANG_WARN_INT_CONVERSION = YES; 244 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 245 | CLANG_WARN_UNREACHABLE_CODE = YES; 246 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 247 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 248 | COPY_PHASE_STRIP = NO; 249 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 250 | ENABLE_NS_ASSERTIONS = NO; 251 | ENABLE_STRICT_OBJC_MSGSEND = YES; 252 | GCC_C_LANGUAGE_STANDARD = gnu99; 253 | GCC_NO_COMMON_BLOCKS = YES; 254 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 255 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 256 | GCC_WARN_UNDECLARED_SELECTOR = YES; 257 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 258 | GCC_WARN_UNUSED_FUNCTION = YES; 259 | GCC_WARN_UNUSED_VARIABLE = YES; 260 | IPHONEOS_DEPLOYMENT_TARGET = 9.2; 261 | MTL_ENABLE_DEBUG_INFO = NO; 262 | SDKROOT = iphoneos; 263 | TARGETED_DEVICE_FAMILY = "1,2"; 264 | VALIDATE_PRODUCT = YES; 265 | }; 266 | name = Release; 267 | }; 268 | 6C181A861CE0A6E7003852A1 /* Debug */ = { 269 | isa = XCBuildConfiguration; 270 | buildSettings = { 271 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 272 | INFOPLIST_FILE = VKKeychainIDFV_proj/Info.plist; 273 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 274 | PRODUCT_BUNDLE_IDENTIFIER = "com.baidu.VKKeychainIDFV-proj"; 275 | PRODUCT_NAME = "$(TARGET_NAME)"; 276 | }; 277 | name = Debug; 278 | }; 279 | 6C181A871CE0A6E7003852A1 /* Release */ = { 280 | isa = XCBuildConfiguration; 281 | buildSettings = { 282 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 283 | INFOPLIST_FILE = VKKeychainIDFV_proj/Info.plist; 284 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 285 | PRODUCT_BUNDLE_IDENTIFIER = "com.baidu.VKKeychainIDFV-proj"; 286 | PRODUCT_NAME = "$(TARGET_NAME)"; 287 | }; 288 | name = Release; 289 | }; 290 | /* End XCBuildConfiguration section */ 291 | 292 | /* Begin XCConfigurationList section */ 293 | 6C181A691CE0A6E7003852A1 /* Build configuration list for PBXProject "VKKeychainIDFV_proj" */ = { 294 | isa = XCConfigurationList; 295 | buildConfigurations = ( 296 | 6C181A831CE0A6E7003852A1 /* Debug */, 297 | 6C181A841CE0A6E7003852A1 /* Release */, 298 | ); 299 | defaultConfigurationIsVisible = 0; 300 | defaultConfigurationName = Release; 301 | }; 302 | 6C181A851CE0A6E7003852A1 /* Build configuration list for PBXNativeTarget "VKKeychainIDFV_proj" */ = { 303 | isa = XCConfigurationList; 304 | buildConfigurations = ( 305 | 6C181A861CE0A6E7003852A1 /* Debug */, 306 | 6C181A871CE0A6E7003852A1 /* Release */, 307 | ); 308 | defaultConfigurationIsVisible = 0; 309 | }; 310 | /* End XCConfigurationList section */ 311 | }; 312 | rootObject = 6C181A661CE0A6E7003852A1 /* Project object */; 313 | } 314 | -------------------------------------------------------------------------------- /VKKeychainIDFV_proj/VKKeychainIDFV_proj.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /VKKeychainIDFV_proj/VKKeychainIDFV_proj.xcodeproj/project.xcworkspace/xcuserdata/Awhisper.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Awhisper/VKKeychainIDFV/d51455125ed9da49086c8a686d645bf0418fec8b/VKKeychainIDFV_proj/VKKeychainIDFV_proj.xcodeproj/project.xcworkspace/xcuserdata/Awhisper.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /VKKeychainIDFV_proj/VKKeychainIDFV_proj.xcodeproj/xcuserdata/Awhisper.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /VKKeychainIDFV_proj/VKKeychainIDFV_proj.xcodeproj/xcuserdata/Awhisper.xcuserdatad/xcschemes/VKKeychainIDFV_proj.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /VKKeychainIDFV_proj/VKKeychainIDFV_proj.xcodeproj/xcuserdata/Awhisper.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | VKKeychainIDFV_proj.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 6C181A6D1CE0A6E7003852A1 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /VKKeychainIDFV_proj/VKKeychainIDFV_proj/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // VKKeychainIDFV_proj 4 | // 5 | // Created by Awhisper on 16/5/9. 6 | // Copyright © 2016年 baidu. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /VKKeychainIDFV_proj/VKKeychainIDFV_proj/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // VKKeychainIDFV_proj 4 | // 5 | // Created by Awhisper on 16/5/9. 6 | // Copyright © 2016年 baidu. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 25 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /VKKeychainIDFV_proj/VKKeychainIDFV_proj/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /VKKeychainIDFV_proj/VKKeychainIDFV_proj/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /VKKeychainIDFV_proj/VKKeychainIDFV_proj/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /VKKeychainIDFV_proj/VKKeychainIDFV_proj/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /VKKeychainIDFV_proj/VKKeychainIDFV_proj/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // VKKeychainIDFV_proj 4 | // 5 | // Created by Awhisper on 16/5/9. 6 | // Copyright © 2016年 baidu. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /VKKeychainIDFV_proj/VKKeychainIDFV_proj/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // VKKeychainIDFV_proj 4 | // 5 | // Created by Awhisper on 16/5/9. 6 | // Copyright © 2016年 baidu. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "UIDevice+VKKeychainIDFV.h" 11 | @interface ViewController () 12 | 13 | @end 14 | 15 | @implementation ViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | 20 | NSString * uuid = [UIDevice VKKeychainIDFV]; 21 | // Do any additional setup after loading the view, typically from a nib. 22 | } 23 | 24 | - (void)didReceiveMemoryWarning { 25 | [super didReceiveMemoryWarning]; 26 | // Dispose of any resources that can be recreated. 27 | } 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /VKKeychainIDFV_proj/VKKeychainIDFV_proj/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // VKKeychainIDFV_proj 4 | // 5 | // Created by Awhisper on 16/5/9. 6 | // Copyright © 2016年 baidu. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | --------------------------------------------------------------------------------