How do you programmatically detect your iPad's generation? - objective-c

I'm working on a program that needs to be able to detect whether or not camera hardware is present in the iPad. I assumed that the easiest way to do this was to determine what generation the device was, but if there is a simpler way to detect the hardware that works too. The iPads that this application is being designed for will likely be recently purchased and running on a standard updated version of iOS.

Nope You can simply check what device is being used!
For checking all iOS devices:
NSString *deviceType = [UIDevice currentDevice].model;
NSLog(deviceType);
In order to check for a camera
if ([UIImagePickerController isSourceTypeAvailable: UIImagePickerControllerSourceTypeCamera])
//there is a camera

Related

KIF (Keep It Functional) distinguish between iPhone and iPad

I am using KIF for testing the functionality of an app. However, this app has two versions, one is for iPad, and the other one is for iPhone. Is there a global variable or something that indicates if I am running my test in iPad or iPhone? I'd like to use it (e.g. in a conditional) to take advantage and just make a few modifications in the iPhone tests that I have already finished.
You can define macro
#define IS_IPAD (UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPhone)
That's how we used it.

Change iOS Simulator Device Name

I'm working on a big project with many view controllers. Progression through these views depends on data being filled in on lengthy forms.
In my not-so-clever way i'm autofilling data so that i can speed through to the current feature I'm working on. I was using a conditional like this...
if(
[[[UIDevice currentDevice] name] hasPrefix:#"Rob"] ||
[[[UIDevice currentDevice] name] hasPrefix:#"iPad Simulator"]
)
{
self.label.text = #"xxx";
...
}
...this worked great because I could test both on my iPad and in the simulator. Now the client wants to also be able to test on their simulator, so I can't leave my autofill in. I'm thinking the simplest solution would be to just change the name of the simulator.
In Settings.app on the simulator, it's not editable. I also haven't seen then text "iPad Simulator" or "Simulator" show up in any files in ~/Library/Application Support/iPhone Simulator/5.1. I've done searches on setting plist properties, but no luck.
Does anyone know how to accomplish this?
You'll be able to check if it's running the iPhone Simulator by checking the model rather than the name of the current device. Something like the following should do:
if ([[[UIDevice currentDevice] model] isEqualToString:#"iPhone Simulator"]) {
// Run for iPhone simulator
}
Note: You'll need to use "iPad Simulator" for when you use the iPad Simulator
Also, your current code with hasPrefix is not secure at all. Rob is a common name so if someone else has a device with the name of their device beginning with Rob then it'll expose your test information. I highly suggest you just target this autocomplete for the simulator only
Just create a new class and put your loading logic there.
After that, call this class from your delegate didFinishLaunchingWithOptions method.
With this, you can comment the above call whenever you want or better, check if the data is already loaded and ignore it.

Sound does only work on Device but not in Simulator

I am playing some short sounds on my iPad like so: Play a short sound in iOS
I am using a caf file which I can successfully play from the Finder. Now I went through quite a bit of a hassle trying to achieve the playback of the sound and I am curious what might be the problems which I don't seem to understand:
Option 1: When I create the SystemSoundID and then play it right away I don't hear anything on the device and the simulator.
Option 2: When I create an instance variable for the SystemSoundID and initialize it in viewDidLoad I manage to play sound but only on the iPad, not the Simulator.
Option 3: Instead of using SystemSoundID I can also use AVAudioPlayer to playback a .wav file which then works on both the iPad and the Simulator but here I need to create the AVAudioPlayer in viewDidLoad otherwise I won't get any sound if I do everything in one go.
The best option currently seems to be Option 3 because it works on both the Simulator and the iPad, but because I need to pre-initialize the Player I would need an AVAudioPlayer instance for every different sound that I want to play, which does not seem to be very memory-wise...
Is there something that I am missing and is it possible to play sounds on both platforms using the AudioToolbox framework (Option 1 & Option 2)
I wrote a library to simplify all this. It wraps AVAudioPlayer, and works fine on both the device and simulator.
https://github.com/nicklockwood/SoundManager
The code is fairly straightforward, although I do some semi-clever stuff to initialise the audio player. If you don't want to use the library you can just copy the code.
A word of warning though - the simulator throws some odd exceptions internally whenever you use AVAudioPlayer. They don't affect the app at all, but if you have enabled break-on-exceptions in Xcode then the app will drop into the debugger a few times during startup and you'll have to manually resume, which may freak you out if you're not expecting it.

How do I exclude iPad 2 and iPod Touch 5th Generation in a function?

I'm trying to create a function that works on ALL iOS devices except the iPad 2 and the iPod Touch 5th Gen.
- (void)doSomething {
// if iPad 2 or iPod 5th Gen
if ()
{
NSLog(#"You're using an iPad 2 or iPod 5th Gen. Sorry!");
}
else
{
NSLog(#"Any other iOS device. Congrats!");
} }
Can someone post a quick sample snippet of how I would accomplish this?
If your app has a major hardware requirement (i.e., it can't really function/do anything useful if the hardware isn't present on the device), you should add an entry to the UIRequiredDeviceCapabilities entry in your Info.plist for your app. This will keep people who don't have the necessary hardware to use your app from purchasing it/downloading it by accident. It will also cause the App store to show a list of all the models that support your software, so people can see what they need in order to use it.
If your app has a function that requires something specific, there are generally in-framework tests you can do to see if the device has the required features/hardware. If this isn't your app's central purpose, you can then enable/disable this feature of your app based on the device's capabilities. You wouldn't want to try and query which device the user is running (except in maybe very limited circumstances), but would rather query whether the device is capable of doing what you want.
Since you mentioned an auto-focusing camera, we'll use that as an example. If your app requires this to do anything useful, you should add the UIRequiredDeviceCapabilities key to your Info.plist file and add the entry auto-focus-camera to the array. This will ensure that only users who have a device with an auto-focusing camera will be able to purchase and install your app. For more information on UIKit keys for Info.plist, including this one, see the Information Property List Key Reference.
If, on the other hand, your app is usable by any device but has a feature that requires an auto-focusing camera, you can test for it's presence using the AVFoundation framework. You can get what you need here from the AVCaptureDevice class. For example, to check if you have access to an auto-focusing camera for video/stills:
// Check for the default camera
AVCaptureDevice* camera = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
if( camera && [camera isFocusModeSupported:AVCaptureFocusModeAutoFocus] ) {
// this device has a default video source capable of autofocus, so enable the feature
} else {
// this device does not have the required hardware, so disable the feature
}
Check this:
if ([[AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo] isFocusModeSupported:AVCaptureFocusModeAutoFocus]) {
//device with autofocus
}
else {
//device without autofocus
}

Better way to detect if isIpad?

I have an universal app that changes the screen layout based on what device the user has.
It seems to work pretty good, but I've had one user call in (and send me screen shots) of his iPhone 4 showing him the iPad view instead of the iPhone view. I haven't been able to duplicate it on any of the phones we have around here, but I'm wondering if there there is a better way to do this since iOS 4.3 has come out.
+(BOOL)isIpad{
return ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad);
}
Alternately, is there just a way to detect screen size? I mostly use this to determine how wide elements in a table should be, but if Apple comes out with iPad 3 with retina display, it would be nice to have the app just adjust everything accordingly.
Also useful if the app is in portrait or landscape. Make it so that it just anchors to the edges like elements in WPF.
When loading XIBs for a universal app this, or what you're already doing, seems to be the only way:
NSString *xibName = (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)?#"SomeView~iPad":#"SomeView";
As for screen size this should work:
CGRect screenSize = [[UIScreen mainScreen] bounds];
This is like a bazillion years old, but came across it in google so I figured I'd post a poorly documented but very useful feature. If you add ~ipad to the end of the filename for your iPad specific nib it will automatically load that one instead. Same logic as #2x for loading images. So your iPhone nib would be named myview.xib and your ipad myview~ipad.xib and iOS will correctly load the ipad version wherever needed. Fancy!
UIUserInterfaceIdiomPad is now deprecated. The new way to do it would be using TraitCollections. It can only be called on Views.
-(BOOL) isiPad{
return self.view.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassRegular && self.view.traitCollection.verticalSizeClass == UIUserInterfaceSizeClassRegular;
}
Refer Apple Documentation here
Probably it has a previous version of the app and conflict with the new!
Try to remove old one and reinstall new! It works! I already encountered this issue.