create NSBundle - iphone

I want to create an application that work with iphone 3 and 4.
so I have images for iphone 3 and others for 4.
now I want my application to load resources based on ios version
the part of detecting ios version is easy.
the problem is that i want to know how to create new NSBundle and use it to make application load resources from different bundle based on detected ios version.

if your resource is only concerned with image then you are not required to put any extra effort to do that. Suppose you have a image named myHome.png for 3 then rename the same image for 4 to myHome#2x.png. It will automatically take that image if the device is iPhone4.
If the resource is any thing other than image then you need to do conditional coding i.e you need to check for a condition every time you are trying to access such resource and the code will look something like this
1 to check if its iPhone of iPad do this
NSString *deviceType = [UIDevice currentDevice].model;
if([deviceType isEqualToString:#"iPhone"])
{
//do your work for iPhone
}
2 To check between iOS version you can try this link this the best I know

Related

Adapt app from iOS7 to iOS6

I wrote my application for iPhone in xcode 5.0 and it supports only 7 ios.
How can I make it available for ios 6?
Also interested in how to prevent applications load on ipad?
First question: Make sure your deployment target is 6.0, don't use API's that are iOS 7 only, or check by using
if ([someObject respondsToSelector:#selector(ios7onlymethod)] {
// do your iOS 7 only stuff
} else {
// Fall back to iOS 6-supported ways
}
Or use
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0f) {
// do your iOS 7 only stuff
} else {
// Fall back to iOS 6-supported ways
}
New frameworks you want to use should be marked as optional in Xcode; to do that select your target, click general, and scroll to the "Linked Frameworks and Libraries" section.
What's really cool is that classes in frameworks marked as optional are replaced with nil on versions of iOS that don't have them. So suppose you write some code like this, using a class from the Sprite Kit framework, new in iOS 7:
SKSpriteNode *spriteNode = [SKSpriteNode spriteWithImageNamed:#"mySprite"];
On iOS 6, when the linker, which "links" frameworks to apps (apps don't copy frameworks, they just get them from the system), sees SKSpriteNode in your code, and the framework is marked as optional, that line of code will be replaced by this:
... = [nil spriteWithImageNamed:#"mySprite"];
Sending messages to nil in Objective-C does absolutely nothing, so the above code doesn't crash. No problem. So instead of lingering your code with if-statements checking for the existence of a class, you can just go with the flow and let the dynamic linker do the work.
Further reading:
iOS 7 UI Transition Guide: Supporting iOS 6
Supporting Multiple iOS Versions and Devices
Second question: There is no way to say that you want your app to only run on iPhones and iPod touches. You can require things that are specifical to the iPhone and iPod touch (like a certain processor architecture or the M7 motion coprocessor) but Apple won't like it if you require the M7 chip to exclude a certain device when you don't even need it. You should probably think about why you don't want your app to run on iPads.

Assets naming for iPhone and iPad

Is it possible to have an image asset named architecture.png and rename it as architecture~ipad.png for the iPad version? And still use it in code as:
[UIImage imageWithName:#"architecture.png"];
will this then look for architecture~ipad for the iPad version?
If you have two image resources in your app:
"architecture.png" (iPhone version)
"architecture~ipad.png" (iPad version)
then
[UIImage imageWithName:#"architecture.png"]
will automatically load the correct one on iPhone/iPad devices.
(As DOOManiac correctly noticed, this works on iOS 4 and later.)
For more information, see "iOS Supports Device-Specific Resources" in the Resource Programming Guide.
Update:
From the link iOS Supports Device-Specific Resources, It looks like this is possible from iOS 4.0 onwards.
In iOS 4.0 and later, it is possible to mark individual resource files
as usable only on a specific type of device. This capability
simplifies the code you have to write for Universal applications.
Rather than creating separate code paths to load one version of a
resource file for iPhone and a different version of the file for iPad,
you can let the bundle-loading routines choose the correct file. All
you have to do is name your resource files appropriately.
To associate a resource file with a particular device, you add a
custom modifier string to its filename. The inclusion of this modifier
string yields filenames with the following format:
<basename><device>.<filename_extension>
The <basename> string represents the original name of the resource
file. It also represents the name you use when accessing the file from
your code. Similarly, the <filename_extension> string is the standard
filename extension used to identify the type of the file. The <device>
string is a case-sensitive string that can be one of the following
values:
~ipad - The resource should be loaded on iPad devices only.
~iphone - The resource should be loaded on iPhone or iPod touch
devices only.
You can apply device modifiers to any type of resource file. For
example, suppose you have an image named MyImage.png. To specify
different versions of the image for iPad and iPhone, you would create
resource files with the names MyImage~ipad.png and MyImage~iphone.png
and include them both in your bundle. To load the image, you would
continue to refer to the resource as MyImage.png in your code and let
the system choose the appropriate version, as shown here:
UIImage* anImage = [UIImage imageNamed:#"MyImage.png"]; On an iPhone
or iPod touch device, the system loads the MyImage~iphone.png resource
file, while on iPad, it loads the MyImage~ipad.png resource file. If a
device-specific version of a resource is not found, the system falls
back to looking for a resource with the original filename, which in
the preceding example would be an image named MyImage.png.
For devices which supports iOS < 4.0, you can follow the below approach. But I dont think it is needed any more. Still keeping it as it is.
One solution I can think of is, by defining a macro for iPad to append ~ipad.png for every image files. Then always call this macro while using this method as [UIImage imageWithName:imageName(#"architecture")]; which will convert it as [UIImage imageWithName:#"architecture.png"]; for iPhone and [UIImage imageWithName:#"architecture~ipad.png"]; for iPad.
For eg:-
#define IMAGENAME(Name) (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)?[(Name) stringByAppendingString:(#"~ipad.png")]:[(Name) stringByAppendingString:(#".png")]
and then use it as [UIImage imageWithName:IMAGENAME(#"architecture")];
it can also be defined as,
#define IMAGENAME(Name) (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)?[(Name) stringByReplacingOccurrencesOfString:#".png" withString:#"~ipad.png"]:(Name)
and then use it as [UIImage imageWithName:IMAGENAME(#"architecture.png")];
Another solution is to subclass UIImage class and override imageWithName method to have this logic implemented here. You need to search for .png in the name param and replace it with a ~ipad.png for iPad. After that you can directly use it as [UIImage imageWithName:#"architecture.png"] for both iPad and iPhone. This can also be achieved by creating a category on NSObject or UIImage. I dont think there are any other ways to achieve this.

best practice to write app both for ios4.3, ios5 and ipad

I am just started write app for ios.
I have 2 questions.
I know there are some codes which work fine in ios4.3 but don't work in ios5 and the opposite is also true.I want to know,which is the best practice for writing app both for ios4.3 and ios5?Is it acceptable run-time to check the version for specific parts of code??
I am also should write same app for ipad. So, I want to know which is the best practice for writing app for iphone which works also on ipad??
Thanks
iOS 5 or iOS 4
Another way to detect the version is to use the respondsToSelector: message on objects. The advantage compared to the version method is that you don't need to know what the next versions of iOS are gonna be to maintain your application. (What if, for instance, a new 5.0.2 version shows up? Your app should know that the "5.0.2" string is newer than "5.0"? I agree it would not be complicated to code, but using respondsToSelector: is much more convenient)
iPhone/iPod Touch or iPad
My usual way to code universal app (ie iPhone and iPad) is to define a basic implementation of my custom UIViewController classes, and then implement an HD version of it, inheriting the default behavior but customizing it for the iPad (overriding methods works well but the delegate pattern might be better: you get compilation warnings if you forget to implement methods).
If you use a different .xib file from the beginning of your application lifecycle (that's what you get by universal Xcode-provided templates), you may end up defining classes just from Interface Builder, and won't need to implement any runtime test in your code to know if you're running on an iPhone or an iPad.
You can get the version using:
[[UIDevice currentDevice] systemVersion];
The systemVersion returns a string, like "5.0". You can then compare the strings using string comparison. For example:
NSString *requiredVersion = #"5.0";
NSString *currentVersion = [[UIDevice currentDevice] systemVersion];
if ([currentVersion compare:requiredVersion options:NSNumericSearch] != NSOrderedAscending)
isItSupported = TRUE;
The documentation indicates that you can use the following to determine if you have an iPhone or iPad:
[[UIDevice currentDevice] model];
I've not used this though.
See the documentation.

Application Platform Specification

I am designing an app for iphone & ipod the client wants the Some of the UI Specification for iphone and ipod to be different so i decided to create different XIB Files for iphone and ipod as in universal apps for iphone and ipod but the problem is that i am not able differentiate between iphone and ipod on run time is there any way to check platform on runtime so as to load different Nib Files on runtime
If there is any code or tutorial please guide me to the link
Thanks in advance
[[UIDevice currentDevice] model] looks like the right source for this Information. You can check it if it contains iPod Touch or iPhone or.....
Check the model property of UIDevice class
http://developer.apple.com/library/ios/#documentation/uikit/reference/UIDevice_Class/Reference/UIDevice.html
However, if you switch on that string, be aware that the simulator shows up as a separate device.
This:
NSString* model = [[UIDevice currentDevice] model];
NSLog(#"model: %#", model);
Outputs:
2011-10-25 08:44:30.794 Craplet[921:b303] model: iPhone Simulator
I think this was already asked several times .)
NSString *dtype = [UIDevice currentDevice].model;
if([dtype isEqualToString:#"iPhone"])
{
// iphone
}
Possible examples of model strings are #”iPhone” and #”iPod touch”

How do I run a universal app on the iPhone 3.1.3 simulator?

I'm working on a new app that I want to be universal for the iPhone and iPad. I started out with the "Create a Window-based app" wizard, and it created separate app delegates in "iPhone" and "iPad" groups. Since I already was quite familiar with iPhone dev, I did that part of my project, and now I'm ready to do some iPad stuff.
So... I started out by adding a UISplitViewController to my iPad delegate, switch the Active SDK to 3.2, and it works! But when I switch back to 3.1.3, and try to run it in the simulator, Build and Go fails. For starters, I see:
...path.../iPad/AppDelegate_Pad.h:13: error: expected specifier-qualifier-list before 'UISplitViewController'
I've got my Base SDK set to 3.2 and my Deployment Target set to 3.1.3. I thought that was enough. But I also have found in the documentation this method to conditionally compile:
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 30200
MyIPadViewController* vc;
// Create the iPad view controller
#else
MyIPhoneViewController* vc;
// Create the iPhone view controller
#endif
So do I need to do this everywhere? It seems like an awful lot of code to add (that I'll be getting rid of in a short time for 4.0 anyway) so I feel like I must be doing something wrong. And, I don't even have any idea how this works for things like #property or #synthesize declarations.
tl;dr version of the question - did I miss a setting somewhere?
I use this C function to help keep the code concise:
BOOL isPad() {
return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad);
}
Another thing I do, when I have different xib files for iPhone vs iPad. I have a stripPadSuffixOnPhone() function that helps keep the code simpler:
// Load/create the Delete table cell with delete button
self.deleteCell = [Utilities loadNib:stripPadSuffixOnPhone(#"DeleteCell~ipad")
ClassName:#"DeleteCell"
Owner:self];
Things like that can make coding more straightforward and a lot less conditionals. Still have to test everything twice though.
Quite the opposite. A universal app runs the same binary on iPhone and iPad so you cannot use conditional compilation to differentiate between the two version. But you need to use the macro Apple cites in the documentation:
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
// iPad-specific code
} else {
// iPhone-specific code
}
Here's what works for me:
Build your app using SDK 3.2.
Switch the active SDK to iPhone Simulator 3.1.3 (or whatever).
From the Run menu select Debug (not Build and Debug).
The binary built under 3.2 will be installed in the 3.x simulator without rebuilding. When you are finished don't forget to set your active SDK back to 3.2.