├── KeychainIDFA.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── KeychainIDFA ├── AppDelegate.h ├── AppDelegate.m ├── Base.lproj │ ├── LaunchScreen.xib │ └── Main.storyboard ├── Images.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Info.plist ├── KeychainIDFA │ ├── KeychainHelper.h │ ├── KeychainHelper.m │ ├── KeychainIDFA.h │ └── KeychainIDFA.m ├── ViewController.h ├── ViewController.m └── main.m └── README.md /KeychainIDFA.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 994A97B31A42769200EEA677 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 994A97B21A42769200EEA677 /* main.m */; }; 11 | 994A97B61A42769200EEA677 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 994A97B51A42769200EEA677 /* AppDelegate.m */; }; 12 | 994A97B91A42769200EEA677 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 994A97B81A42769200EEA677 /* ViewController.m */; }; 13 | 994A97BC1A42769200EEA677 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 994A97BA1A42769200EEA677 /* Main.storyboard */; }; 14 | 994A97BE1A42769200EEA677 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 994A97BD1A42769200EEA677 /* Images.xcassets */; }; 15 | 994A97C11A42769200EEA677 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 994A97BF1A42769200EEA677 /* LaunchScreen.xib */; }; 16 | 994A97D91A42770E00EEA677 /* KeychainHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 994A97D81A42770E00EEA677 /* KeychainHelper.m */; }; 17 | 994A97DC1A42806900EEA677 /* KeychainIDFA.m in Sources */ = {isa = PBXBuildFile; fileRef = 994A97DB1A42806900EEA677 /* KeychainIDFA.m */; }; 18 | /* End PBXBuildFile section */ 19 | 20 | /* Begin PBXFileReference section */ 21 | 994A97AD1A42769200EEA677 /* KeychainIDFA.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = KeychainIDFA.app; sourceTree = BUILT_PRODUCTS_DIR; }; 22 | 994A97B11A42769200EEA677 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 23 | 994A97B21A42769200EEA677 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 24 | 994A97B41A42769200EEA677 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 25 | 994A97B51A42769200EEA677 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 26 | 994A97B71A42769200EEA677 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 27 | 994A97B81A42769200EEA677 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 28 | 994A97BB1A42769200EEA677 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 29 | 994A97BD1A42769200EEA677 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 30 | 994A97C01A42769200EEA677 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 31 | 994A97D71A42770E00EEA677 /* KeychainHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KeychainHelper.h; sourceTree = ""; }; 32 | 994A97D81A42770E00EEA677 /* KeychainHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KeychainHelper.m; sourceTree = ""; }; 33 | 994A97DA1A42806900EEA677 /* KeychainIDFA.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KeychainIDFA.h; sourceTree = ""; }; 34 | 994A97DB1A42806900EEA677 /* KeychainIDFA.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KeychainIDFA.m; sourceTree = ""; }; 35 | /* End PBXFileReference section */ 36 | 37 | /* Begin PBXFrameworksBuildPhase section */ 38 | 994A97AA1A42769200EEA677 /* Frameworks */ = { 39 | isa = PBXFrameworksBuildPhase; 40 | buildActionMask = 2147483647; 41 | files = ( 42 | ); 43 | runOnlyForDeploymentPostprocessing = 0; 44 | }; 45 | /* End PBXFrameworksBuildPhase section */ 46 | 47 | /* Begin PBXGroup section */ 48 | 994A97A41A42769200EEA677 = { 49 | isa = PBXGroup; 50 | children = ( 51 | 994A97AF1A42769200EEA677 /* KeychainIDFA */, 52 | 994A97AE1A42769200EEA677 /* Products */, 53 | ); 54 | sourceTree = ""; 55 | }; 56 | 994A97AE1A42769200EEA677 /* Products */ = { 57 | isa = PBXGroup; 58 | children = ( 59 | 994A97AD1A42769200EEA677 /* KeychainIDFA.app */, 60 | ); 61 | name = Products; 62 | sourceTree = ""; 63 | }; 64 | 994A97AF1A42769200EEA677 /* KeychainIDFA */ = { 65 | isa = PBXGroup; 66 | children = ( 67 | 994A97D61A4276ED00EEA677 /* KeychainIDFA */, 68 | 994A97B41A42769200EEA677 /* AppDelegate.h */, 69 | 994A97B51A42769200EEA677 /* AppDelegate.m */, 70 | 994A97B71A42769200EEA677 /* ViewController.h */, 71 | 994A97B81A42769200EEA677 /* ViewController.m */, 72 | 994A97BA1A42769200EEA677 /* Main.storyboard */, 73 | 994A97BD1A42769200EEA677 /* Images.xcassets */, 74 | 994A97BF1A42769200EEA677 /* LaunchScreen.xib */, 75 | 994A97B01A42769200EEA677 /* Supporting Files */, 76 | ); 77 | path = KeychainIDFA; 78 | sourceTree = ""; 79 | }; 80 | 994A97B01A42769200EEA677 /* Supporting Files */ = { 81 | isa = PBXGroup; 82 | children = ( 83 | 994A97B11A42769200EEA677 /* Info.plist */, 84 | 994A97B21A42769200EEA677 /* main.m */, 85 | ); 86 | name = "Supporting Files"; 87 | sourceTree = ""; 88 | }; 89 | 994A97D61A4276ED00EEA677 /* KeychainIDFA */ = { 90 | isa = PBXGroup; 91 | children = ( 92 | 994A97D71A42770E00EEA677 /* KeychainHelper.h */, 93 | 994A97D81A42770E00EEA677 /* KeychainHelper.m */, 94 | 994A97DA1A42806900EEA677 /* KeychainIDFA.h */, 95 | 994A97DB1A42806900EEA677 /* KeychainIDFA.m */, 96 | ); 97 | path = KeychainIDFA; 98 | sourceTree = ""; 99 | }; 100 | /* End PBXGroup section */ 101 | 102 | /* Begin PBXNativeTarget section */ 103 | 994A97AC1A42769200EEA677 /* KeychainIDFA */ = { 104 | isa = PBXNativeTarget; 105 | buildConfigurationList = 994A97D01A42769200EEA677 /* Build configuration list for PBXNativeTarget "KeychainIDFA" */; 106 | buildPhases = ( 107 | 994A97A91A42769200EEA677 /* Sources */, 108 | 994A97AA1A42769200EEA677 /* Frameworks */, 109 | 994A97AB1A42769200EEA677 /* Resources */, 110 | ); 111 | buildRules = ( 112 | ); 113 | dependencies = ( 114 | ); 115 | name = KeychainIDFA; 116 | productName = KeychainIDFA; 117 | productReference = 994A97AD1A42769200EEA677 /* KeychainIDFA.app */; 118 | productType = "com.apple.product-type.application"; 119 | }; 120 | /* End PBXNativeTarget section */ 121 | 122 | /* Begin PBXProject section */ 123 | 994A97A51A42769200EEA677 /* Project object */ = { 124 | isa = PBXProject; 125 | attributes = { 126 | LastUpgradeCheck = 0610; 127 | ORGANIZATIONNAME = Qixin; 128 | TargetAttributes = { 129 | 994A97AC1A42769200EEA677 = { 130 | CreatedOnToolsVersion = 6.1.1; 131 | }; 132 | }; 133 | }; 134 | buildConfigurationList = 994A97A81A42769200EEA677 /* Build configuration list for PBXProject "KeychainIDFA" */; 135 | compatibilityVersion = "Xcode 3.2"; 136 | developmentRegion = English; 137 | hasScannedForEncodings = 0; 138 | knownRegions = ( 139 | en, 140 | Base, 141 | ); 142 | mainGroup = 994A97A41A42769200EEA677; 143 | productRefGroup = 994A97AE1A42769200EEA677 /* Products */; 144 | projectDirPath = ""; 145 | projectRoot = ""; 146 | targets = ( 147 | 994A97AC1A42769200EEA677 /* KeychainIDFA */, 148 | ); 149 | }; 150 | /* End PBXProject section */ 151 | 152 | /* Begin PBXResourcesBuildPhase section */ 153 | 994A97AB1A42769200EEA677 /* Resources */ = { 154 | isa = PBXResourcesBuildPhase; 155 | buildActionMask = 2147483647; 156 | files = ( 157 | 994A97BC1A42769200EEA677 /* Main.storyboard in Resources */, 158 | 994A97C11A42769200EEA677 /* LaunchScreen.xib in Resources */, 159 | 994A97BE1A42769200EEA677 /* Images.xcassets in Resources */, 160 | ); 161 | runOnlyForDeploymentPostprocessing = 0; 162 | }; 163 | /* End PBXResourcesBuildPhase section */ 164 | 165 | /* Begin PBXSourcesBuildPhase section */ 166 | 994A97A91A42769200EEA677 /* Sources */ = { 167 | isa = PBXSourcesBuildPhase; 168 | buildActionMask = 2147483647; 169 | files = ( 170 | 994A97B91A42769200EEA677 /* ViewController.m in Sources */, 171 | 994A97B61A42769200EEA677 /* AppDelegate.m in Sources */, 172 | 994A97B31A42769200EEA677 /* main.m in Sources */, 173 | 994A97D91A42770E00EEA677 /* KeychainHelper.m in Sources */, 174 | 994A97DC1A42806900EEA677 /* KeychainIDFA.m in Sources */, 175 | ); 176 | runOnlyForDeploymentPostprocessing = 0; 177 | }; 178 | /* End PBXSourcesBuildPhase section */ 179 | 180 | /* Begin PBXVariantGroup section */ 181 | 994A97BA1A42769200EEA677 /* Main.storyboard */ = { 182 | isa = PBXVariantGroup; 183 | children = ( 184 | 994A97BB1A42769200EEA677 /* Base */, 185 | ); 186 | name = Main.storyboard; 187 | sourceTree = ""; 188 | }; 189 | 994A97BF1A42769200EEA677 /* LaunchScreen.xib */ = { 190 | isa = PBXVariantGroup; 191 | children = ( 192 | 994A97C01A42769200EEA677 /* Base */, 193 | ); 194 | name = LaunchScreen.xib; 195 | sourceTree = ""; 196 | }; 197 | /* End PBXVariantGroup section */ 198 | 199 | /* Begin XCBuildConfiguration section */ 200 | 994A97CE1A42769200EEA677 /* Debug */ = { 201 | isa = XCBuildConfiguration; 202 | buildSettings = { 203 | ALWAYS_SEARCH_USER_PATHS = NO; 204 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 205 | CLANG_CXX_LIBRARY = "libc++"; 206 | CLANG_ENABLE_MODULES = YES; 207 | CLANG_ENABLE_OBJC_ARC = YES; 208 | CLANG_WARN_BOOL_CONVERSION = YES; 209 | CLANG_WARN_CONSTANT_CONVERSION = YES; 210 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 211 | CLANG_WARN_EMPTY_BODY = YES; 212 | CLANG_WARN_ENUM_CONVERSION = YES; 213 | CLANG_WARN_INT_CONVERSION = YES; 214 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 215 | CLANG_WARN_UNREACHABLE_CODE = YES; 216 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 217 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 218 | COPY_PHASE_STRIP = NO; 219 | ENABLE_STRICT_OBJC_MSGSEND = YES; 220 | GCC_C_LANGUAGE_STANDARD = gnu99; 221 | GCC_DYNAMIC_NO_PIC = NO; 222 | GCC_OPTIMIZATION_LEVEL = 0; 223 | GCC_PREPROCESSOR_DEFINITIONS = ( 224 | "DEBUG=1", 225 | "$(inherited)", 226 | ); 227 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 228 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 229 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 230 | GCC_WARN_UNDECLARED_SELECTOR = YES; 231 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 232 | GCC_WARN_UNUSED_FUNCTION = YES; 233 | GCC_WARN_UNUSED_VARIABLE = YES; 234 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 235 | MTL_ENABLE_DEBUG_INFO = YES; 236 | ONLY_ACTIVE_ARCH = YES; 237 | SDKROOT = iphoneos; 238 | }; 239 | name = Debug; 240 | }; 241 | 994A97CF1A42769200EEA677 /* Release */ = { 242 | isa = XCBuildConfiguration; 243 | buildSettings = { 244 | ALWAYS_SEARCH_USER_PATHS = NO; 245 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 246 | CLANG_CXX_LIBRARY = "libc++"; 247 | CLANG_ENABLE_MODULES = YES; 248 | CLANG_ENABLE_OBJC_ARC = YES; 249 | CLANG_WARN_BOOL_CONVERSION = YES; 250 | CLANG_WARN_CONSTANT_CONVERSION = YES; 251 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 252 | CLANG_WARN_EMPTY_BODY = YES; 253 | CLANG_WARN_ENUM_CONVERSION = YES; 254 | CLANG_WARN_INT_CONVERSION = YES; 255 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 256 | CLANG_WARN_UNREACHABLE_CODE = YES; 257 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 258 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 259 | COPY_PHASE_STRIP = YES; 260 | ENABLE_NS_ASSERTIONS = NO; 261 | ENABLE_STRICT_OBJC_MSGSEND = YES; 262 | GCC_C_LANGUAGE_STANDARD = gnu99; 263 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 264 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 265 | GCC_WARN_UNDECLARED_SELECTOR = YES; 266 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 267 | GCC_WARN_UNUSED_FUNCTION = YES; 268 | GCC_WARN_UNUSED_VARIABLE = YES; 269 | IPHONEOS_DEPLOYMENT_TARGET = 6.0; 270 | MTL_ENABLE_DEBUG_INFO = NO; 271 | SDKROOT = iphoneos; 272 | VALIDATE_PRODUCT = YES; 273 | }; 274 | name = Release; 275 | }; 276 | 994A97D11A42769200EEA677 /* Debug */ = { 277 | isa = XCBuildConfiguration; 278 | buildSettings = { 279 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 280 | INFOPLIST_FILE = KeychainIDFA/Info.plist; 281 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 282 | PRODUCT_NAME = "$(TARGET_NAME)"; 283 | }; 284 | name = Debug; 285 | }; 286 | 994A97D21A42769200EEA677 /* Release */ = { 287 | isa = XCBuildConfiguration; 288 | buildSettings = { 289 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 290 | INFOPLIST_FILE = KeychainIDFA/Info.plist; 291 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 292 | PRODUCT_NAME = "$(TARGET_NAME)"; 293 | }; 294 | name = Release; 295 | }; 296 | /* End XCBuildConfiguration section */ 297 | 298 | /* Begin XCConfigurationList section */ 299 | 994A97A81A42769200EEA677 /* Build configuration list for PBXProject "KeychainIDFA" */ = { 300 | isa = XCConfigurationList; 301 | buildConfigurations = ( 302 | 994A97CE1A42769200EEA677 /* Debug */, 303 | 994A97CF1A42769200EEA677 /* Release */, 304 | ); 305 | defaultConfigurationIsVisible = 0; 306 | defaultConfigurationName = Release; 307 | }; 308 | 994A97D01A42769200EEA677 /* Build configuration list for PBXNativeTarget "KeychainIDFA" */ = { 309 | isa = XCConfigurationList; 310 | buildConfigurations = ( 311 | 994A97D11A42769200EEA677 /* Debug */, 312 | 994A97D21A42769200EEA677 /* Release */, 313 | ); 314 | defaultConfigurationIsVisible = 0; 315 | }; 316 | /* End XCConfigurationList section */ 317 | }; 318 | rootObject = 994A97A51A42769200EEA677 /* Project object */; 319 | } 320 | -------------------------------------------------------------------------------- /KeychainIDFA.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /KeychainIDFA/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // KeychainIDFA 4 | // 5 | // Created by Qixin on 14/12/18. 6 | // Copyright (c) 2014年 Qixin. 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 | -------------------------------------------------------------------------------- /KeychainIDFA/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // KeychainIDFA 4 | // 5 | // Created by Qixin on 14/12/18. 6 | // Copyright (c) 2014年 Qixin. 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 | -------------------------------------------------------------------------------- /KeychainIDFA/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /KeychainIDFA/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 | -------------------------------------------------------------------------------- /KeychainIDFA/Images.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 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /KeychainIDFA/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.qixin.$(PRODUCT_NAME:rfc1034identifier) 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 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /KeychainIDFA/KeychainIDFA/KeychainHelper.h: -------------------------------------------------------------------------------- 1 | // 2 | // KeychainHelper.h 3 | // KeychainIDFA 4 | // 5 | // Created by Qixin on 14/12/18. 6 | // Copyright (c) 2014年 Qixin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface KeychainHelper : NSObject 12 | + (void)save:(NSString *)service data:(id)data; 13 | + (id)load:(NSString *)service; 14 | + (void)delete:(NSString *)service; 15 | @end 16 | -------------------------------------------------------------------------------- /KeychainIDFA/KeychainIDFA/KeychainHelper.m: -------------------------------------------------------------------------------- 1 | // 2 | // KeychainHelper.m 3 | // KeychainIDFA 4 | // 5 | // Created by Qixin on 14/12/18. 6 | // Copyright (c) 2014年 Qixin. All rights reserved. 7 | // 8 | 9 | #import "KeychainHelper.h" 10 | #import 11 | 12 | @implementation KeychainHelper 13 | 14 | + (NSMutableDictionary *)getKeychainQuery:(NSString *)service 15 | { 16 | return [NSMutableDictionary dictionaryWithObjectsAndKeys: 17 | (__bridge id)(kSecClassGenericPassword),kSecClass, 18 | service, kSecAttrService, 19 | service, kSecAttrAccount, 20 | kSecAttrAccessibleAfterFirstUnlock,kSecAttrAccessible,nil]; 21 | } 22 | 23 | + (void)save:(NSString *)service data:(id)data 24 | { 25 | NSMutableDictionary *keychainQuery = [self getKeychainQuery:service]; 26 | SecItemDelete((__bridge CFDictionaryRef)(keychainQuery)); 27 | [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] 28 | forKey:(__bridge id)(kSecValueData)]; 29 | SecItemAdd((__bridge CFDictionaryRef)(keychainQuery), NULL); 30 | } 31 | 32 | + (id)load:(NSString *)service 33 | { 34 | id ret = nil; 35 | NSMutableDictionary *keychainQuery = [self getKeychainQuery:service]; 36 | [keychainQuery setObject:(id)kCFBooleanTrue forKey:(__bridge id)(kSecReturnData)]; 37 | [keychainQuery setObject:(__bridge id)(kSecMatchLimitOne) forKey:(__bridge id)(kSecMatchLimit)]; 38 | 39 | CFTypeRef result = NULL; 40 | if (SecItemCopyMatching((__bridge_retained CFDictionaryRef)keychainQuery, &result) == noErr) 41 | { 42 | ret = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge NSData*)result]; 43 | } 44 | return ret; 45 | } 46 | 47 | + (void)delete:(NSString *)service 48 | { 49 | NSMutableDictionary *keychainQuery = [self getKeychainQuery:service]; 50 | SecItemDelete((__bridge CFDictionaryRef)(keychainQuery)); 51 | } 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /KeychainIDFA/KeychainIDFA/KeychainIDFA.h: -------------------------------------------------------------------------------- 1 | // 2 | // KeychainIDFA.h 3 | // KeychainIDFA 4 | // 5 | // Created by Qixin on 14/12/18. 6 | // Copyright (c) 2014年 Qixin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //设置你idfa的Keychain标示,该标示相当于key,而你的IDFA是value 12 | #define IDFA_STRING @"com.qixin.test.idfa" 13 | 14 | @interface KeychainIDFA : NSObject 15 | 16 | //获取IDFA 17 | + (NSString*)IDFA; 18 | 19 | //删除keychain的IDFA(一般不需要) 20 | + (void)deleteIDFA; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /KeychainIDFA/KeychainIDFA/KeychainIDFA.m: -------------------------------------------------------------------------------- 1 | // 2 | // KeychainIDFA.m 3 | // KeychainIDFA 4 | // 5 | // Created by Qixin on 14/12/18. 6 | // Copyright (c) 2014年 Qixin. All rights reserved. 7 | // 8 | 9 | #import "KeychainIDFA.h" 10 | #import "KeychainHelper.h" 11 | @import AdSupport; 12 | 13 | #define kIsStringValid(text) (text && text!=NULL && text.length>0) 14 | 15 | 16 | 17 | @implementation KeychainIDFA 18 | 19 | 20 | + (void)deleteIDFA 21 | { 22 | [KeychainHelper delete:IDFA_STRING]; 23 | } 24 | 25 | + (NSString*)IDFA 26 | { 27 | //0.读取keychain的缓存 28 | NSString *deviceID = [KeychainIDFA getIdfaString]; 29 | if (kIsStringValid(deviceID)) 30 | { 31 | return deviceID; 32 | } 33 | else 34 | { 35 | //1.取IDFA,可能会取不到,如用户关闭IDFA 36 | if ([ASIdentifierManager sharedManager].advertisingTrackingEnabled) 37 | { 38 | deviceID = [[[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString] lowercaseString]; 39 | [KeychainIDFA setIdfaString:deviceID]; 40 | return deviceID; 41 | } 42 | else 43 | { 44 | //2.如果取不到,就生成UUID,当成IDFA 45 | deviceID = [KeychainIDFA getUUID]; 46 | [KeychainIDFA setIdfaString:deviceID]; 47 | if (kIsStringValid(deviceID)) 48 | { 49 | return deviceID; 50 | } 51 | } 52 | } 53 | //3.再取不到尼玛我也没办法了,你牛B. 54 | return nil; 55 | } 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | #pragma mark - Keychain 85 | + (NSString*)getIdfaString 86 | { 87 | NSString *idfaStr = [KeychainHelper load:IDFA_STRING]; 88 | if (kIsStringValid(idfaStr)) 89 | { 90 | return idfaStr; 91 | } 92 | else 93 | { 94 | return nil; 95 | } 96 | } 97 | 98 | + (BOOL)setIdfaString:(NSString *)secValue 99 | { 100 | if (kIsStringValid(secValue)) 101 | { 102 | [KeychainHelper save:IDFA_STRING data:secValue]; 103 | return YES; 104 | } 105 | else 106 | { 107 | return NO; 108 | } 109 | } 110 | 111 | 112 | 113 | #pragma mark - UUID 114 | + (NSString*)getUUID 115 | { 116 | CFUUIDRef uuid_ref = CFUUIDCreate(kCFAllocatorDefault); 117 | CFStringRef uuid_string_ref= CFUUIDCreateString(kCFAllocatorDefault, uuid_ref); 118 | 119 | CFRelease(uuid_ref); 120 | NSString *uuid = [NSString stringWithString:(__bridge NSString*)uuid_string_ref]; 121 | if (!kIsStringValid(uuid)) 122 | { 123 | uuid = @""; 124 | } 125 | CFRelease(uuid_string_ref); 126 | return [uuid lowercaseString]; 127 | } 128 | 129 | 130 | @end 131 | -------------------------------------------------------------------------------- /KeychainIDFA/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // KeychainIDFA 4 | // 5 | // Created by Qixin on 14/12/18. 6 | // Copyright (c) 2014年 Qixin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /KeychainIDFA/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // KeychainIDFA 4 | // 5 | // Created by Qixin on 14/12/18. 6 | // Copyright (c) 2014年 Qixin. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "KeychainIDFA.h" 11 | 12 | //第一次:2d54d261-7bae-4014-8b81-3f9ff969b6e1 13 | //第二次:2d54d261-7bae-4014-8b81-3f9ff969b6e1 14 | //卸载app启动:2d54d261-7bae-4014-8b81-3f9ff969b6e1 15 | 16 | //delete之后:2b8d8afc-7f87-4c9c-ac73-ec64a89fc1a8 17 | //delete之后2次:2b8d8afc-7f87-4c9c-ac73-ec64a89fc1a8 18 | //delete之后卸载:2b8d8afc-7f87-4c9c-ac73-ec64a89fc1a8 19 | 20 | @interface ViewController () 21 | 22 | @end 23 | 24 | @implementation ViewController 25 | 26 | - (void)viewDidLoad 27 | { 28 | [super viewDidLoad]; 29 | //[KeychainIDFA deleteIDFA]; 30 | NSLog(@"%@",[KeychainIDFA IDFA]); 31 | } 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /KeychainIDFA/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // KeychainIDFA 4 | // 5 | // Created by Qixin on 14/12/18. 6 | // Copyright (c) 2014年 Qixin. 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | KeychainIDFA 2 | ============ 3 | 4 | 获取idfa标示当设备唯一识别,并保存到keychain中.基本不变.除非刷机. 5 | 6 | 7 | ### 测试数据 8 | 9 | //第一次:2d54d261-7bae-4014-8b81-3f9ff969b6e1 10 | //第二次:2d54d261-7bae-4014-8b81-3f9ff969b6e1 11 | //卸载app启动:2d54d261-7bae-4014-8b81-3f9ff969b6e1 12 | 13 | //delete之后:2b8d8afc-7f87-4c9c-ac73-ec64a89fc1a8 14 | //delete之后2次:2b8d8afc-7f87-4c9c-ac73-ec64a89fc1a8 15 | //delete之后卸载:2b8d8afc-7f87-4c9c-ac73-ec64a89fc1a8 16 | 17 | 18 | ### 使用方式 19 | 20 | //设置你idfa的Keychain标示,该标示相当于key,而你的IDFA是value 21 | //在KeychainIDFA.h中定义 22 | #define IDFA_STRING @"com.qixin.test.idfa" 23 | 24 | #import "KeychainIDFA.h" 25 | 26 | [KeychainIDFA IDFA]//获取IDFA 27 | 28 | [KeychainIDFA deleteIDFA]//删除Keychain中IDFA(一般不用) 29 | --------------------------------------------------------------------------------