How can I get UI_USER_INTERFACE_IDIOM - iphone

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)

Related

Xcode 5, How to build an app with UI compatible with IOS 6 as well as IOS 7 [duplicate]

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...
}

How to detect iOS device programmatically

I need to know which iOS device is currently running app (saying more exactly I need to know is device armv6 or armv7). UIUserInterfaceIdiomPad() could not check is device an iPhone4S or iPhone3G. Is it possible?
Download https://github.com/erica/uidevice-extension (UIDevice-Hardware class) and you can use these:
[UIDevice currentDevice] platformType] // returns UIDevice4GiPhone
[[UIDevice currentDevice] platformString] // returns #"iPhone 4G"
Or check if its retina
+ (BOOL) isRetina
{
if([[UIScreen mainScreen] respondsToSelector:#selector(scale)])
return [[UIScreen mainScreen] scale] == 2.0 ? YES : NO;
return NO;
}
Or check iOs version
+ (BOOL) isIOS5
{
NSString *os5 = #"5.0";
NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
// currSysVer = #"5.0.1";
if ([currSysVer compare:os5 options:NSNumericSearch] == NSOrderedAscending) //lower than 4
{
return NO;
}
else if ([currSysVer compare:os5 options:NSNumericSearch] == NSOrderedDescending) //5.0.1 and above
{
return YES;
}
else // IOS 5
{
return YES;
}
return NO;
}
If you really want to know (at run time) if you are running on arm6 or arm7, you can use "NXGetArchInfoFromCPUType" (much more detail is available in the accepted answer to this question).
Otherwise you can use platformType or platformString, as our incredibly quick answering friend Omar suggested (and +1 to him!).

How to build app with iOS 5.0 methods for iOS 4.3?

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
}

ipad 2 camera support detection

I have an app that uses the following Macro:
#define IS_IPAD ([[UIDevice currentDevice] respondsToSelector:#selector(userInterfaceIdiom)] && [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad)
which works very well for me.
However, I was using it to turn off the option of taking a photo in the app.
How can I detect if the camera option is available regardless of device?
[UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera];
That should work
See How to Detect Camera Existence with AVFoundation.
NSArray *videoDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
AVCaptureDevice *captureDevice = nil;
if ( [videoDevices count] > 0 ) // This device has one or more cameras
....

Best way to programmatically detect iPad/iPhone hardware

The reason I need to find out is that on an iPad, a UIPickerView has the same height in landscape orientation as it does in portrait. On an iPhone it is different. The iPad programming guide introduces an "idiom" value to UIDevice:
UIDevice* thisDevice = [UIDevice currentDevice];
if(thisDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad)
{
// iPad
}
else
{
// iPhone
}
which works OK while you're in iPad (3.2) but not iPhone (3.1.3) - so it looks like there also needs to be an ifdef to conditionally compile that check, like:
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 30200
UIDevice* thisDevice = [UIDevice currentDevice];
if(thisDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad)
{
// etc.
}
#endif
To me that's starting to look very clumsy. What's a better way?
Checking at runtime (your first way) is completely different from #if at compile time. The preprocessor directives won't give you a universal app.
The preferred way is to use Apple's Macro:
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
// The device is an iPad running iPhone 3.2 or later.
}
else
{
// The device is an iPhone or iPod touch.
}
Use 3.2 as the base SDK (because the macro is not defined pre 3.2), you can target prior OS versions to get it running on the iPhone.
I'm answering this now (and at this late date) because many of the existing answers are quite old, and the most Up Voted actually appears to be wrong according to Apples current docs (iOS 8.1, 2015)!
To prove my point, this is the comment from Apples header file (always look at the Apple source and headers):
/*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.*/
Therefore, the currently APPLE recommended way to detect iPhone vs. iPad, is as follows:
1) (DEPRECATED as of iOS 13) On versions of iOS PRIOR to 3.2, use the Apple provided macro:
// for iPhone use UIUserInterfaceIdiomPhone
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
2) On versions of iOS 3.2 or later, use the property on [UIDevice currentDevice]:
// for iPhone use UIUserInterfaceIdiomPhone
if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad)
I like my isPad() function. Same code but keep it out of sight and in only one place.
My solution (works on 3.2+):
#define IS_IPHONE (!IS_IPAD)
#define IS_IPAD (UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPhone)
then,
if (IS_IPAD)
// do something
or
if (IS_IPHONE)
// do something else
In Swift use userInterfaceIdiom instance property as-
if UIDevice.current.userInterfaceIdiom == .phone {
print("iPhone")
}
& For other devices -
switch UIDevice.current.userInterfaceIdiom {
case .pad:
print("iPad")
case .phone:
print("iPhone")
case .tv:
print("TV")
case .carPlay:
print("carPlay")
default: break;
}
Put this method in your App Delegate so that you can call it anywhere using [[[UIApplication sharedApplication] delegate] isPad]
-(BOOL)isPad
{
BOOL isPad;
NSRange range = [[[UIDevice currentDevice] model] rangeOfString:#"iPad"];
if(range.location==NSNotFound)
{
isPad=NO;
}
else {
isPad=YES;
}
return isPad;
}
If you are using features that are not backwards compatible, I found the best way for me is to create a #define in the pre-compiled header. Example:
#if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_3_2
#define USING_4_X
#endif
Then in your code, you can do this:
BOOL exists = NO;
#ifdef USING_4_X
exists = [SomeObject someMethod:[url lastPathComponent]];
#else
exists = [SomeObject someMethod:[[url path] lastPathComponent]];
#endif
If
1- you already have the app installed into your device,
2- you change its build settings to be a 'Universal' app,
3- install the app to your device on top of the pre-existing app (without deleting the previous one)
You might find that the solutions provided here to detect iPhone/iPad do not work. First, delete the app that was 'only' for iPad/iPhone and install it fresh to your device.
BOOL isIpad()
{
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
return YES;
}
return NO;
}
extension UIDevice {
var isIPad: Bool {
return UIDevice.current.userInterfaceIdiom == .pad
}
}