I just update my Xcode to 5. I am trying to build my app and it looks very nice on iOS7 but I have problems with the toolbars. The buttons on toolbar are very close to the status bar. IF Ui make some changes then it breakes the UI for iOS 5 and 6.
What is the best approach? Building different storyboard for iOS 7 is considered as good approach? Is there any other way to fix the issue with toolbars?
Best approach is just to add a lot of checks to the iOS version before doing any changes. Place the following macros in your *_prefix.pch file
#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)
and then use like this for iOS 7 specific functionality:
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"7.0")) {
self.automaticallyAdjustsScrollViewInsets = YES;
// or anything. Above line not specific to question, just an example
}
In Xcode 5 Interface Builder you are also able to specify offsets between iOS 7 & 6 or lower in the Size Inspector (Fourth tab in the Utilities (third) column) and switch between 7 and < 7 renderings in the File Inspector (first tab in the Utilities column). This usually comes into play when you have to account for the status bar or navigation bar in the layouts in 7.
Related
This question already has an answer here:
iOS 6 UI distorted [closed]
(1 answer)
Closed 9 years ago.
I am using Xcode 5.
I want to build an app with UI compatible with both IOS 6 as well IOS 7. Can anyone help me with this. App should be compatible with iPhone (3gs), iPhone retina 3.5 and iPhone retina 4.
UI gets distorted when i watch it on iPhone (3GS) having IOS 6.
I have tried enabling Auto layout, But still the problem persists for some of the screens.
1: If you are using UINavigationController and your navigation bar is visible then this works
float systemVersion=[[[UIDevice currentDevice]systemVersion]floatValue];
if(systemVersion >=7.0f)
{
self.edgesForExtendedLayout=UIRectEdgeNone;
}
OR
You can also set from stoyboard
2: Another solution is . You can use IOS 6/7 Deltas
i) take new view and setting its Y postion is 20
ii) move all control into this view
iii)setting new view Detas Y Property is -20
Now you view hirerachy is look like as
You can see in follwing image how to set Deltas property
There are several macros which are helpful in this case
#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)
#define APP_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[[NSBundle mainBundle] infoDictionary] objectForKey:#"CFBundleVersion"] compare:v options:NSNumericSearch] != NSOrderedAscending)
To see is your iOS version is greater than iOS7:
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"7.0")) {
// iOS 7 specific instruction
}
However is this IF-ELSE is still long, you can do something like this
#define IS_IOS_7 SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"7.0")
and then
if (IS_IOS_7) {
// instruction...
}
I'm finishing iCloud feature for my app and can't solve one problem:
Since I'm using some new 5.0 features like NSFileCoordinator, I can't build my app for 4.3 because of "dyld: Symbol not found: _OBJC_CLASS_$_NSFileCoordinator".
How can I "untarget" some files (which have iCloud methods) for building 4.3 version?
Thanks in advance!
Have a look at this.
Class cls = NSClassFromString (#"NSFileCoordinator");
if (cls) {
// Create an instance of the class and use it.
} else {
// Alternate code path to follow when the
// class is not available.
}
Also check this answer to see why
you should avoid relying on the version string as an indication of device or OS capabilities.
To just take them out of the source copilation:
Click on your project file.
Go to "Build Phases".
Expand "Compile Sources".
Select the file you dont want, and press the "-" button at the
bottom of the section.
Or you can delete it from the project (just remove the reference rather than deleting the file), and it will remove it from this section as well.
Or you could create preprocessor macros to check to see if the user can run the functions
// System Versioning Preprocessor Macros
#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)
/* Usage
if (SYSTEM_VERSION_LESS_THAN(#"4.0")) {
...
}
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"3.1.1")) {
...
}*/
With this, you can check to see what systen version the user is using and only build for 5.0, but put in functioning code for if it is a version less than 5.0.
I think it's better to turn off iCloud feature for 4.3 builds altogether. You can do that by check iOS version at runtime. In your particular case you could check for presence of NSFileCoordinator class with NSClassFromString() function, but I'm pretty sure there are more decent ways on the internet of accomplishing this.
You could make a new build target and set a compiler preprocessing Macro like NO_CLOUD and then use
#ifdef NO_CLOUD
... code here ...#else
... cloud code here ... #endif
You have to weak link to the framwork's (when you add a framework to the project just set it as optional not required).
In the h file you have to import only if you have ios 5
#if defined(__IPHONE_5_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_5_0
#import <Twitter/Twitter.h>
#import <Accounts/Accounts.h>
#endif
and in the m file you have to try to create class from string and test to see if you have the class. And also test top see if the class responds to selectors.
Class TWTweetComposeViewControllerClass = NSClassFromString(#"TWTweetComposeViewController");
if (TWTweetComposeViewControllerClass != nil) {
if([TWTweetComposeViewControllerClass respondsToSelector:#selector(canSendTweet)]) {
UIViewController *twitterViewController = [[TWTweetComposeViewControllerClass alloc] init];
[twitterViewController performSelector:#selector(setInitialText:)
withObject:NSLocalizedString(#"TwitterMessage", #"")];
[twitterViewController performSelector:#selector(addURL:)
withObject:url];
[twitterViewController performSelector:#selector(addImage:)
withObject:[UIImage imageNamed:#"yourImage.png"]];
[self.navigationController presentModalViewController:twitterViewController animated:YES];
[twitterViewController release];
}
} else {
//do something else
}
My example is based on twitter engine you have to adapt it to your classes.
Build it with latest SDK (5.0). It will tun both 4.3 and 5.0
And you can check IOS version
if ([[UIDevice currentDevice] systemVersion] floatValue] >= 5.0f) {
// iCloud
} else {
// iCloudless
}
I am on a new project. I want my code compatible to be for both IOS4 and IOS5 SDKs. I need all my functionalities work both in IOS4 and IOS5. That said, i am not planning to use new features in IOS5 (feature wise) and disable that feature for IOS4.
I have 2 options. Let me know which is best ?
Target and code for IOS4. and that will work fine in IOS5 also, i think.
BaseSDK IOS5 and target IOS4 .(I am not planning to use ARC or storyboard for now anyway ).
I think with method #2, i have to be extra careful while using each usages at the same time as i am not using story board and ARC , there are no benefits. So hope #1 is better.
Let me know expert opinion.
Note: in future if need to switch to IOS5 new features , hope only this ARC will be the blocking and that is also an optional thing and i can easily switch rt?
I use this code to support my app on multiple iOS versions (3.0, 4.0, 5.0) ..
put this at the top (along with imports)
#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)
then if there are some OS specific features, use them like this (I am using AlertView as an example. Pre iOS5, UIAlertView does not support a custom textView inside it, so I had my own custom AlertView. In iOS5, that hack does not work and I have to use UIAlertView as it supports custom textViews):
if (SYSTEM_VERSION_LESS_THAN(#"5.0")) {
TextAlertView *alert = [[TextAlertView alloc] initWithTitle:#"xxxYYzz"
message:#""
delegate:self cancelButtonTitle:#"Add"
otherButtonTitles:#"Cancel", nil];
alert.textField.keyboardType = UIKeyboardTypeDefault;
alert.tag = 1;
self.recipeNameTextField = alert.textField;
[alert show];
[alert release];
}
else {
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:#"xxYYzz"
message:#""
delegate:self cancelButtonTitle:#"Add"
otherButtonTitles:#"Cancel", nil];
alert.alertViewStyle = UIAlertViewStylePlainTextInput;
self.recipeNameTextField = [alert textFieldAtIndex:0];
[alert show];
[alert release];
}
Hope it helps
Go with the first one. If you're making your app for iOS4 and you're not using anything new from iOS5 then don't make things more complicated for yourself.
The only real time you want to use the second option is when you want to use some of the new features in iOS5 but you still want it to be compatible on iOS4, in which case you will have to put in conditional checks for the iOS version that your program is currently being run on.
By the way, ARC is compatible to iOS4 anyway.
At work we build our apps like Option 2 when we need backwards compatibility
This question already has answers here:
How to check iOS version?
(36 answers)
Closed 9 years ago.
I want to check if the user is running the app on iOS less than 5.0 and display a label in the app.
How do I detect which iOS is running on user's device programmatically?
Thanks!
Best current version, without need to deal with numeric search within NSString is to define macros (See original answer: Check iPhone iOS Version)
Those macros do exist in github, see: https://github.com/carlj/CJAMacros/blob/master/CJAMacros/CJAMacros.h
Like this:
#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)
and use them like this:
if (SYSTEM_VERSION_LESS_THAN(#"5.0")) {
// code here
}
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"6.0")) {
// code here
}
Outdated version below
to get OS version:
[[UIDevice currentDevice] systemVersion]
returns string, which can be turned into int/float via
-[NSString floatValue]
-[NSString intValue]
like this
Both values (floatValue, intValue) will be stripped due to its type, 5.0.1 will become 5.0 or 5 (float or int), for comparing precisely, you will have to separate it to array of INTs
check accepted answer here: Check iPhone iOS Version
NSString *ver = [[UIDevice currentDevice] systemVersion];
int ver_int = [ver intValue];
float ver_float = [ver floatValue];
and compare like this
NSLog(#"System Version is %#",[[UIDevice currentDevice] systemVersion]);
NSString *ver = [[UIDevice currentDevice] systemVersion];
float ver_float = [ver floatValue];
if (ver_float < 5.0) return false;
For Swift 4.0 syntax
below example is just checking if the device is of iOS11 or greater version.
let systemVersion = UIDevice.current.systemVersion
if systemVersion.cgFloatValue >= 11.0 {
//"for ios 11"
}
else{
//"ios below 11")
}
Update
From iOS 8 we can use the new isOperatingSystemAtLeastVersion method on NSProcessInfo
NSOperatingSystemVersion ios8_0_1 = (NSOperatingSystemVersion){8, 0, 1};
if ([[NSProcessInfo processInfo] isOperatingSystemAtLeastVersion:ios8_0_1]) {
// iOS 8.0.1 and above logic
} else {
// iOS 8.0.0 and below logic
}
Beware that this will crash on iOS 7, as the API didn't exist prior to iOS 8. If you're supporting iOS 7 and below, you can safely perform the check with
if ([NSProcessInfo instancesRespondToSelector:#selector(isOperatingSystemAtLeastVersion:)]) {
// conditionally check for any version >= iOS 8 using 'isOperatingSystemAtLeastVersion'
} else {
// we're on iOS 7 or below
}
Original answer iOS < 8
For the sake of completeness, here's an alternative approach proposed by Apple itself in the iOS 7 UI Transition Guide, which involves checking the Foundation Framework version.
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1) {
// Load resources for iOS 6.1 or earlier
} else {
// Load resources for iOS 7 or later
}
I know I am too late to answer this question. I am not sure does my method still working on low iOS versions (< 5.0):
NSString *platform = [UIDevice currentDevice].model;
NSLog(#"[UIDevice currentDevice].model: %#",platform);
NSLog(#"[UIDevice currentDevice].description: %#",[UIDevice currentDevice].description);
NSLog(#"[UIDevice currentDevice].localizedModel: %#",[UIDevice currentDevice].localizedModel);
NSLog(#"[UIDevice currentDevice].name: %#",[UIDevice currentDevice].name);
NSLog(#"[UIDevice currentDevice].systemVersion: %#",[UIDevice currentDevice].systemVersion);
NSLog(#"[UIDevice currentDevice].systemName: %#",[UIDevice currentDevice].systemName);
You can get these results:
[UIDevice currentDevice].model: iPhone
[UIDevice currentDevice].description: <UIDevice: 0x1cd75c70>
[UIDevice currentDevice].localizedModel: iPhone
[UIDevice currentDevice].name: Someones-iPhone002
[UIDevice currentDevice].systemVersion: 6.1.3
[UIDevice currentDevice].systemName: iPhone OS
[[UIDevice currentDevice] systemVersion]
[[UIDevice currentDevice] systemVersion];
or check the version like
You can get the below Macros from here.
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(IOS_VERSION_3_2_0))
{
UIImageView *background = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"cs_lines_back.png"]] autorelease];
theTableView.backgroundView = background;
}
Hope this helps
[[[UIDevice currentDevice] systemVersion] floatValue]
Marek Sebera's is great most of the time, but if you're like me and find that you need to check the iOS version frequently, you don't want to constantly run a macro in memory because you'll experience a very slight slowdown, especially on older devices.
Instead, you want to compute the iOS version as a float once and store it somewhere. In my case, I have a GlobalVariables singleton class that I use to check the iOS version in my code using code like this:
if ([GlobalVariables sharedVariables].iOSVersion >= 6.0f) {
// do something if iOS is 6.0 or greater
}
To enable this functionality in your app, use this code (for iOS 5+ using ARC):
GlobalVariables.h:
#interface GlobalVariables : NSObject
#property (nonatomic) CGFloat iOSVersion;
+ (GlobalVariables *)sharedVariables;
#end
GlobalVariables.m:
#implementation GlobalVariables
#synthesize iOSVersion;
+ (GlobalVariables *)sharedVariables {
// set up the global variables as a static object
static GlobalVariables *globalVariables = nil;
// check if global variables exist
if (globalVariables == nil) {
// if no, create the global variables class
globalVariables = [[GlobalVariables alloc] init];
// get system version
NSString *systemVersion = [[UIDevice currentDevice] systemVersion];
// separate system version by periods
NSArray *systemVersionComponents = [systemVersion componentsSeparatedByString:#"."];
// set ios version
globalVariables.iOSVersion = [[NSString stringWithFormat:#"%01d.%02d%02d", \
systemVersionComponents.count < 1 ? 0 : \
[[systemVersionComponents objectAtIndex:0] integerValue], \
systemVersionComponents.count < 2 ? 0 : \
[[systemVersionComponents objectAtIndex:1] integerValue], \
systemVersionComponents.count < 3 ? 0 : \
[[systemVersionComponents objectAtIndex:2] integerValue] \
] floatValue];
}
// return singleton instance
return globalVariables;
}
#end
Now you're able to easily check the iOS version without running macros constantly. Note in particular how I converted the [[UIDevice currentDevice] systemVersion] NSString to a CGFloat that is constantly accessible without using any of the improper methods many have already pointed out on this page. My approach assumes the version string is in the format n.nn.nn (allowing for later bits to be missing) and works for iOS5+. In testing, this approach runs much faster than constantly running the macro.
Hope this helps anyone experiencing the issue I had!
In MonoTouch:
To get the Major version use:
UIDevice.CurrentDevice.SystemVersion.Split('.')[0]
For minor version use:
UIDevice.CurrentDevice.SystemVersion.Split('.')[1]
To get more specific version number information with major and minor versions separated:
NSString* versionString = [UIDevice currentDevice].systemVersion;
NSArray* vN = [versionString componentsSeparatedByString:#"."];
The array vN will contain the major and minor versions as strings, but if you want to do comparisons, version numbers should be stored as numbers (ints). You can add this code to store them in the C-array* versionNumbers:
int versionNumbers[vN.count];
for (int i = 0; i < sizeof(versionNumbers)/sizeof(versionNumbers[0]); i++)
versionNumbers[i] = [[vN objectAtIndex:i] integerValue];
* C-arrays used here for more concise syntax.
A simple check for iOS version less than 5 (all versions):
if([[[UIDevice currentDevice] systemVersion] integerValue] < 5){
// do something
};
How can I get UI_USER_INTERFACE_IDIOM, I am not clear that how does it work, can anyone please guide me?
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
// iPad device
} else {
// iPhone / iPod touch device
}
From the Apple Header files:
/* The UI_USER_INTERFACE_IDIOM() macro is provided for use when deploying to a version of the iOS less than 3.2. If the earliest version of iPhone/iOS that you will be deploying for is 3.2 or greater, you may use -[UIDevice userInterfaceIdiom] directly. */
#define UI_USER_INTERFACE_IDIOM() ([[UIDevice currentDevice] respondsToSelector:#selector(userInterfaceIdiom)] ? [[UIDevice currentDevice] userInterfaceIdiom] : UIUserInterfaceIdiomPhone)