Read device's udid with base SDK 7.0 - ios

I have to read the iOS device's udid in a project with base SDK 7.0 (I know I'm not supposed to, but I need to read it and the identifierForVendor is not an option). I have to to this only on iOS 6 devices, but the method uniqueIdentifier is not recognized because of the base SDK. Since I don't know how to determine the iOS version at compile time, I did the following:
#define SYSTEM_IS_IOS_7 ([[[UIDevice currentDevice] systemVersion] compare:#"7.0" options:NSNumericSearch] != NSOrderedAscending)
...
if (!SYSTEM_IS_IOS_7) {
SEL selector = NSSelectorFromString(#"uniqueIdentifier");
if ([[UIDevice currentDevice] respondsToSelector:selector]) {
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:
[[[UIDevice currentDevice] class] instanceMethodSignatureForSelector:selector]];
[invocation setSelector:selector];
[invocation setTarget:[UIDevice currentDevice]];
[invocation invoke];
NSString *udid = nil;
[invocation getReturnValue:&udid];
NSLog(#"%#", udid);
}
}
I'm running the code on iOS 6.1, the udid appears on the console, but the app crashes right after that with EXC_BAD_ACCESS in the main.m, with no message on the console. Any idea why and how to solve this?

Related

iOS7 app backward compatible with iOS5 regarding unique identifier

My app is compatible with iOS5 and iOS6.
Until now I had no problem using:
NSString DeviceID = [[UIDevice currentDevice] uniqueIdentifier];
Now with iOS7 and with uniqueIdentifier not working anymore I changed to:
NSString DeviceID = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
The problem is, this would not work for iOS5.
How can I achieve backward compatibility with iOS5?
I tried this, with no luck:
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 60000
// iOS 6.0 or later
NSString DeviceID = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
#else
// iOS 5.X or earlier
NSString DeviceID = [[UIDevice currentDevice] uniqueIdentifier];
#endif
The best and recommend option by Apple is:
NSString *adId = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
Use it for every device above 5.0.
For 5.0 you have to use uniqueIdentifier. The best to check if it's available is:
if (!NSClassFromString(#"ASIdentifierManager"))
Combining that will give you:
- (NSString *) advertisingIdentifier
{
if (!NSClassFromString(#"ASIdentifierManager")) {
SEL selector = NSSelectorFromString(#"uniqueIdentifier");
if ([[UIDevice currentDevice] respondsToSelector:selector]) {
return [[UIDevice currentDevice] performSelector:selector];
}
//or get macaddress here http://iosdevelopertips.com/device/determine-mac-address.html
}
return [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
}
Why just not to use CFUUIDRef and be independent with iOS verion?
CFUUIDRef uuidRef = CFUUIDCreate(kCFAllocatorDefault);
self.uuidString = (NSString *)CFUUIDCreateString(NULL,uuidRef);
CFRelease(uuidRef);
And of course remember calculated uuidString in the Keychain(in case of application removal)?
Here is written how to use keychain
As hard replacement of static macro, you can try dynamic if statement to check it.
UIDevice has property named 'systemVersion' and you can check this.

The [UIDevice uniqueIdentifier] become private in iOS 6.0

Apple doesn't allowed to add application to the app store that used the [UIDevice uniqueIdentifier] because the property become private in iOS SDK 6.0
What are the Alternatives?
you can use/create "your own" UDID:
+(NSString *)getUUID
{
CFUUIDRef newUniqueId = CFUUIDCreate(kCFAllocatorDefault);
NSString * uuidString = (__bridge_transfer NSString*)CFUUIDCreateString(kCFAllocatorDefault, newUniqueId);
CFRelease(newUniqueId);
return uuidString;
}
You should keep in mind that this method will produce a different id on every call so you should persist it some how, thus it is not an identical alternative to the UDID, but for most uses it is even better like that.
#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
- (NSString*)deviceId {
NSString *udidString;
if (SYSTEM_VERSION_LESS_THAN(#"6.0")) {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
udidString = [defaults objectForKey:#"udidKey"];
if (!udidString) {
CFUUIDRef identifierObject = CFUUIDCreate(kCFAllocatorDefault);
// Convert the CFUUID to a string
udidString = (NSString *)CFUUIDCreateString(kCFAllocatorDefault, identifierObject);
[defaults setObject:udidString forKey:#"udidKey"];
[defaults synchronize];
CFRelease((CFTypeRef) identifierObject);
}
} else {
udidString = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
}
return udidString;
}
if gets warning on the line: udidString = [[[UIDevice currentDevice] identifierForVendor] UUIDString]; it means the Xcode SDK is less than 6.0
(Xcode 4.3 contains iOS SDK 5.1, Xcode 4.5 contains iOS SDK 6.0)
to update Xcode iOS SDK:
simply download the newest Xcode available on App Store (Apple doesn't give an option to download only the SDK).
if want to keep current Xcode version just:
download the newest Xcode version.
copy iOS SDK Library from :
newestXcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/
to
oldXcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/
Reopen old Xcode and thats it!

uniqueIdentifier vs. indentifierForVendor and Apple rejection

I have a question about uniqueIdentifier vs identifierforVendor. We use the UDID for login identification purposes and we are in the process of switching over to the new iOS 6 version of forVendor...
My questions are this
1) Is Apple rejecting apps that are still using uniqueIdentifier?
2) How can they reject this seeing as they don't allow first generation ipads to go up to 6.0?
PS - also found that identifierforVendor doesn't always work in 6.0, looks like it was resolved in 6.0.1
Here is the code I am using... do you think it will get rejected?
static inline NSString* UniqueDeviceId() {
if ([[[UIDevice currentDevice] systemVersion] compare:#"6.0.1" options:NSNumericSearch] != NSOrderedAscending)
return [[[UIDevice currentDevice] identifierForVendor] UUIDString];
return [[UIDevice currentDevice] uniqueIdentifier];
}
thanks
While I can't speak for the Apple review team. it is unlikely you will be rejected for using this deprecated API as long as your app supports a version of iOS that doesn't have the alternative.
I would update your code to properly check for the new method:
if ([[UIDevice currentDevice] respondsToSelector:#selector(identifierForVendor)]) {
return [[[UIDevice currentDevice] identifierForVendor] UUIDString];
} else {
return [[UIDevice currentDevice] uniqueIdentifier];
}
now Apps are not permitted to access the UDID and must not use the uniqueIdentifier method of UIDevice. Please update your apps and servers to associate users with the Vendor or Advertising identifiers introduced in iOS 6
NSUUID *uuid = [[UIDevice currentDevice] identifierForVendor];
NSString *uuidString = [uuid UUIDString];
and must to add ADSupport framework

How to check iOS Version is iOS 6? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Check iPhone iOS Version
I want to check iOS Version in iOS.
Because i have some of codes only for iOS 6.
So how can i?
Check this GitHub Gist
https://gist.github.com/998472
You can add the code or include it in your ...-Prefix.pch file so you can use it wherever you need it.
EDIT
I'm leaving an example of how you can use the code from Gist so people can check if it's useful for their case. This can also be found over the Gist.
/*
* Usage
*/
if (SYSTEM_VERSION_LESS_THAN(#"4.0")) {
...
}
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"3.1.1")) {
...
}
Try this:
Update:
NSArray *vComp = [[UIDevice currentDevice].systemVersion componentsSeparatedByString:#"."];
if ([[vComp objectAtIndex:0] intValue] >= 7) {
// iOS-7 code[current] or greater
} else if ([[vComp objectAtIndex:0] intValue] == 6) {
// iOS-6 code
} else if ([[vComp objectAtIndex:0] intValue] > 2) {
// iOS-3,4,5 code
} else {
// iOS-1,2... code: incompatibility warnings, legacy-handlers, etc..
}
Previous code:
NSArray *vComp = [[UIDevice currentDevice].systemVersion componentsSeparatedByString:#"."];
if ([[vComp objectAtIndex:0] intValue] == 6) {
// iOS-6 code
} else {
// iOS-5, iOS-4... code
}
To specifically check for a subversion of IOS use
float sysVer = [[[UIDevice currentDevice] systemVersion] floatValue];
if (sysVer > 6.01) {
// iOS-6.01+ code
} else {
// prior iOS versions
}
You can get the iOS version as a string using:
[[UIDevice currentDevice] systemVersion]

How do I detect whether I have iPhone 2G,3G,3GS

How to detect my current device name through iOS?
Whether you are on an iPhone or a iPod Touch:
UIDevice *device = [UIDevice currentDevice];
NSString *systemName = [device systemName];
To detect the version of the OS:
UIDevice *device = [UIDevice currentDevice];
NSString *systemVersion = [device systemVersion];
To detect a specific model, you would need to test for some capability that only that model has, so to detect an iPhone 3GS, check for a video capability on the camera:
#define SOURCETYPE UIImagePickerControllerSourceTypeCamera
// does the device have a camera?
if ([UIImagePickerController isSourceTypeAvailable:SOURCETYPE]) {
// if so, does that camera support video?
NSArray *mediaTypes = [UIImagePickerController availableMediaTypesForSourceType:SOURCETYPE];
bool isA3GS = [mediaTypes containsObject:kUTTypeMovie];
}
Here is a class written by Erica Sadun that provides extensive capabilities for this:
http://github.com/erica/uidevice-extension/blob/master/UIDevice-Hardware.m
Check out the rest of the repo - there are a few more classes that would prove to be really useful for fine-grained device querying.
From the UIDevice.h file:
[[UIDevice currentDevice] name] // e.g. "My iPhone"
[[UIDevice currentDevice] model] // e.g. #"iPhone", #"iPod Touch"
[[UIDevice currentDevice] localizedModel] // localized version of model
[[UIDevice currentDevice] systemName] // e.g. #"iPhone OS"
[[UIDevice currentDevice] systemVersion] // e.g. #"2.0"
[[UIDevice currentDevice] uniqueIdentifier] // a string unique to each device based on various hardware info.
What you are looking for is this:
UIDevice *device = [UIDevice currentDevice];
NSString *model = [device model];
This will return whether the device is an iPhone or iPod touch

Resources