I have an iPad app that makes use in UIPrintInfo (that is being supported from iOS 4.2 and above).
I want my app to run on previous iOS version such as 3.2.
How can I detect in my code the device's iOS version and make the necessary changes according to the device's version?
Thanks in advance,
Class printInfoClass = NSClassFromString(#"UIPrintInfo");
if (printInfoClass != nil )
{
id printInfo = [printInfoClass printInfo];
// Do something
}
Use
[[UIDevice currentDevice] systemVersion]
Related
I'm using a test library to see me crash report, and I need to know if the app is running from Xcode, I know that exist the DEGUB parameter, but it does not work because if install app from xcode and open it, DEGUB parameter will be in YES.
Thanks.
Not exactly what you want, but you can check if the cable is plugged in, so if it's just for testing the solution should be enough.
[[UIDevice currentDevice] batteryLevel]
or
[[UIDevice currentDevice] UIDeviceBatteryState]
Ah, iOS 8 - lots of unexpected changes from iOS 7 to account for!
tl;dr: Is there a way to programmatically determine the iOS SDK version used to build an app, at run-time (not with a preprocessor macro)?
I'm struggling with some window frame calculations for a library I maintain (distributed as a pre-built static library), as iOS 8 has changed the way the screen coordinate system works.
Two initial observations, running code for iOS 7 with no changes for iOS 8:
When built with the iOS 7 SDK, and run on iOS 8, everything works as prior, no changes necessary.
When built with the iOS 8 SDK, and run on iOS 8, it's broken: some changes in frame calculation are needed to get correct positioning.
So, we change the code, with conditionals on [[UIDevice currentDevice] systemVersion], to work correctly with the new coordinate system. Now:
When built with the iOS 7 SDK, and run on iOS 7, everything works.
When built with the iOS 8 SDK, and run on iOS 8, everything works.
BUT:
When built with the iOS 7 SDK, and run on iOS 8, the calculations are off - remember, when built with the iOS 7 SDK, everything worked fine prior to the iOS 8-specific code changes. So, the changes made actually broke stuff.
Now, normally, I could happily solve this with some macro conditionals on the SDK version (#ifdef __IPHONE_8_0, etc). But I'm distributing a pre-built static library, built with the iOS 7 SDK, so the code within those conditionals would never make it in. Here's why that's a problem:
If the static library is built with the iOS 7 SDK, but linked into an app built with the iOS 8 SDK, it's the same as if the static library were built with the iOS 8 SDK (because the linking happens at the final app compilation stage, of course). That means I need to have those iOS 8 changes in there, when the app is built with the iOS 8 SDK -- but I can't use a macro conditional to determine whether to use them, as the C preprocessor did its thing during the static library build under iOS 7.
So, my question is this: does anyone know how I might be able to determine whether the app build was made with the iOS 8 SDK, at runtime, from within the pre-compiled static library?
I did try checking for an iOS 8-only SDK feature (-[UIScreen nativeBounds], for example), but that doesn't fly -- the symbol's available regardless of SDK version.
Anyone have any ideas?
Empirical, undocumented observations follow:
Apple records the SDK you built against in the Info.plist under the keys DTSDKBuild and DTSDKName, amongst others. Of those DTSDKName seems to be accessible at runtime and ends with the SDK number. So, getting a:
- (NSString *)buildVersion
{
// form character set of digits and punctuation
NSMutableCharacterSet *characterSet =
[[NSCharacterSet decimalDigitCharacterSet] mutableCopy];
[characterSet formUnionWithCharacterSet:
[NSCharacterSet punctuationCharacterSet]];
// get only those things in characterSet from the SDK name
NSString *SDKName = [[NSBundle mainBundle] infoDictionary][#"DTSDKName"];
NSArray *components =
[[SDKName componentsSeparatedByCharactersInSet:
[characterSet invertedSet]]
filteredArrayUsingPredicate:
[NSPredicate predicateWithFormat:#"length != 0"]];
if([components count]) return components[0];
return nil;
}
BOOL wasBuiltWithiOS8SDK =
[[[NSBundle mainBundle] infoDictionary][#"DTSDKBuild"] compare:#"11D167"]
== NSOrderedDescending;
... with the heavy caveat that I've just reverse engineered that, empirically. So it's technically undocumented API and there's no guarantee whatsoever of robustness in the future.
You could then just use:
BOOL wasBuiltForiOS8 =
[[self buildVersion] compare:#"8.0"] != NSOrderedAscending;
(which has the nice feature that it'll evaluate to YES if the version string isn't found, so technically it doesn't matter if Apple takes away DTSDKBuild in the future, it only matters that they don't retroactively remove it from 7.x or somehow one day use a version string that is alphabetically before 8.0)
Here's a provisional solution - hacky, though; it'd be nice to have something more robust.
- (BOOL)hasiOS8ScreenCoordinateBehaviour {
if ( [[[UIDevice currentDevice] systemVersion] floatValue] < 8.0 ) return NO;
CGSize screenSize = [[UIScreen mainScreen] bounds].size;
if ( UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]) &&
screenSize.width < screenSize.height ) {
return NO;
}
return YES;
}
Hi I am developing small iphone application in which I want to generate unique id for my device. I am using following thing :
-(NSString*)uniqueIDForDevice
{
NSString* uniqueIdentifier = nil;
if( [UIDevice instancesRespondToSelector:#selector(identifierForVendor)] ) { // >=iOS 7
uniqueIdentifier = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
} else { //<=iOS6, Use UDID of Device
CFUUIDRef uuid = CFUUIDCreate(NULL);
//uniqueIdentifier = ( NSString*)CFUUIDCreateString(NULL, uuid);- for non- ARC
uniqueIdentifier = ( NSString*)CFBridgingRelease(CFUUIDCreateString(NULL, uuid));// for ARC
CFRelease(uuid);
}
return uniqueIdentifier;
}
So i tested this code locally. Mean Every time when I uninstall and install it again it will create same unique code for me. But when I push it to app store that time for every installation on same device it is generating different code. I want to generate same code for each installation on same device. Is there any method to do this. Need some help.
I want to generate a unique identifier for device which will be same for my device even I install and uninstall application many times. I am using OIS 7.0 version.
Thank you.
The identifierForVendor changes only after a system restore, you can check some of my test here:iOS 7 access UUID value in an enterprise application (not for AppStore).
In case of iOS version lower than ios6 you can save the id in the keychain, it will persist even after app uninstall
In the past I used the following preprocessor code to conditionally execute code for different iOS versions:
#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
// target is iOS
#if __IPHONE_OS_VERSION_MIN_REQUIRED < 60000
// target is lower than iOS 6.0
#else
// target is at least iOS 6.0
#endif
#endif
However with iOS 7 I have the following problem:
#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
// target is iOS
#if __IPHONE_OS_VERSION_MIN_REQUIRED < 70000
// target is lower than iOS 7.0
NSLog(#"This message should only appear if iOS version is 6.x or lower");
#else
// target is at least iOS 7.0
#endif
#endif
The NSLog message above appears on console under iOS 7. Am I doing something wrong?
EDIT: The following code running under iOS 7 (simulator and device)
NSLog(#"Version %i", __IPHONE_OS_VERSION_MIN_REQUIRED);
gives: Version 60000
That is the Deployment Target of your app (the minimum version where your app can be installed), not the version where the app is running in the device.
In the settings of your project, you can set that field:
If you change it like this, this input:
NSLog(#"Version %i", __IPHONE_OS_VERSION_MIN_REQUIRED);
Returns 7000
If what you want is to check the actual version of the operative system, I refer you to this question:
How to check iOS version?
But, it's done in runtime, not at compile time.
#ifdef __AVAILABILITY_INTERNAL__IPHONE_9_0_DEP__IPHONE_9_0
// you're in Xcode 7.x and can use buggy SDK with ios 9.0 only functionality
CGFloat iOSVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
if (iOSVersion>=9) {
// same good old API that predates brave new post Steve Jobs world of bugs and crashes
}
#else
// you're running Xcode 6.4 or older and should use older API here
#endif
swift:
if #available(iOS 13, *) {
toSearchBar?.isHidden = true
} else {
// a path way to discovering how fast UIKit will rot
// now that there is SwiftUI
}
I can find many examples on how to only compile/run code then iOS version is > something, but how do I do it the other way around? I tried the following by running iOS 5.0 in the simulator:
#if __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_6_0
// Code for iOS < 6.0 here
#endif
But the code inside the #if - #endif is not run on iOS 5.0 in the simulator. How can I do this?
[EDIT]
Ok so I wasn't sure what I wanted it seems, sorry :) The thing is that I want this code in my UITableViewDelegate to be run only if the device is running iOS < 6.0:
-(UIView*)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
}
This is because I want to do some styling if I am running iOS < 6, but on iOS 6 I can do this styling much much easier. But a version check at runtime inside this method is not really what I want because then it is to late.
Thank you
Søren
There's a difference between
a compile-time check if you're compiling against a specific SDK and
checking which OS your code is running on
Checking for the __IPHONE_6_0 macro will just check which target you're compiling for... is that what you want? If so, you could use #ifndef __IPHONE_6_0 to check if you are not compiling for iOS 6.
If you want to know which OS your code is running on, you can check MSK's answer.
Here is a run time not compile time check.
#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
use it like
if(SYSTEM_VERSION_LESS_THAN(#"6.0"))
{
}