Cocoa - Need help in switching xibs - iphone

I would really appreciate any help on where I am going wrong. Essentially I have a game app I am developing in XCode4 (Universal) - I have several subview screens (.h .m .xib) that I need to switch between and in some cases reload. Here is how I am doing it in the main AppDelegate.m:
-(void)switchxibs_nextScreen1 {
//close any views first
[self closesuperviews];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
nextGame *theView = [[nextGame alloc] init];
theView.view.tag=101;
[_window addSubview:theView.view];
}
else
{
nextGame_iPhone *theView = [[nextGame_iPhone alloc] init];
theView.view.tag=101;
[_window addSubview:theView.view];
}
}
-(void) switchxibs_nextScreen2 {
//close any views first
[self closesuperviews];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
nextGame *theView = [[nextGame2 alloc] init];
theView.view.tag=101;
[_window addSubview:theView.view];
}
else
{
nextGame_iPhone *theView = [[nextGame2_iPhone alloc] init];
theView.view.tag=101;
[_window addSubview:theView.view];
}
}
-(void)closesuperviews{
for (UIView *subview in _window.subviews) {
// Only remove the subviews with tag equal to 101
if(subview.tag==101){
[subview removeFromSuperview];
}
}
}
I am not sure if this is the way I am supposed to do it. I am running into issues where when switching screens and going back to one it appears that it wasnt properly closed. Any help would be greatly appreciated.

First, you should know that you can eliminate some redundancy in your code by simply naming your xibs with correct format. iOS has certain naming conventions for resources (XIBs, images, et) which allow the OS to load the appropriate resource for different devices. From the iOS Resource Programming Guide...
iOS Supports Device-Specific Resources
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 <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.
So you don't need to do all the manual checking your doing. As for the actual act of switching, knowing more about your app/view structure would help in answering the question, but you should probably be using instances of UIViewController to manage your views, not managing them directly in the app delegate.

Related

Converting an iphone application into an iPad , iOS?

I currently have an iOS iPhone application.
What i want to do , is make it universal so that i can target the iPad too.
What i did , was go to the target and change the iOS application target , from iPhone to universal.
Now when i run the application on my iPad , it automatically resizes all the views for the iPad.
However there are some views , with background pictures that dont look so good , cause i need to use higher resolution pictures or in general i should change some things in the iPad version.
Where are the iPad .nib files??? I mean , i only see the iPhone ones. When i run it on my iphone , these files are used. When i run it on my iPad everything is resized correctly , but where the hell are these .nib files?
The tutorials (pretty old) that i read , suggested that when you target the iPad too , new .nib files should be created exact copies for the ipad. Why i dont see these files?
You can have iOS automatically load the right xib based on the extension, akin to how Retina graphics work. If your xib is named Awesome, and you want to convert it into having an iPhone and an iPad version (instead of being shared, rename it such that:
iPhone version:
Awesome~iphone
iPad version:
Awesome~ipad
Then, when you tell iOS to load Awesome, it'll pick which one to load based on the current platform automagically. No need for if statements in your code! You can still if you want, but it's not required.
Note: You might need to perform a clean after the rename! Sometimes some files stick around in the build when renamed.
You will just need to make new .xib files and set them to the same class and you can init that viewController with a condition:
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
yourVC = [[YourViewController alloc] initWithNibName:"YourViewController_ipad" andBundle:nil];
}
else
{
yourVC = [[YourViewController alloc] initWithNibName:"YourViewController" andBundle:nil];
}
Whenever possible you should try to use the same .xib but in a lot of cases it isn't possible to do that and look good so you just make a second. Xcode won't do it automatically for you.
Let's say that you have a class. We'll call it Two.
Here are the current files that make up the Two class.
Two.h
Two.m
Two.xib
Two.xib contains a UIView sized for the iPhone. In order to make a view sized for the iPad, you should create a new XIB file (name it Two_iPad.xib), connect the XIB to Two, resize the UIView in Two_iPad.xib for the iPad, and design accordingly.
When you are creating a new instance of Two, do the following.
Two *two;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
//they are using an iPad
two = [[Two alloc] initWithNibName:#"Two_iPad" bundle:nil];
} else {
//they are using an iPhone/iPod Touch
two = [[Two alloc] initWithNibName:#"Two" bundle:nil];
}
You are creating a new instance of Two; however, you are checking which device the user has, and using the corresponding XIB file.

Can i connect 2 nib files to the same .h & .m?

I'm trying to make a universal app, so i was wondering if i can connect two nib files ( 1 for iPad and the other for iphone ) to the same .h and .m files ?
i have 3 files TestView.h TestView.m and TestView.xib.... how can i connect a TestView_iPad.xib to the same TestView.h and TestView.m ?
i'm new to Xcode and i'm using Xcode 4 right now
thanx in advance :)
Short answer: Yes.
Provided you follow the model/view/controller style, you can re-use the same View and Viewcontroller (.h and .m) files in both an iPad nib and an iPhone nib (or storyboard). There will be occasions when you need to use the following type of code, though:
BOOL iPad = (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad);
if (iPad) {
.... iPad specific code like SplitViewController
} else {
.... iPhone / iPod Touch specific code
}
You may also need to check if the view controller you are in is on-screen (as on the iPad more than one ViewController can be onscreen), in which case use:
if (self.view.window) {
.... ViewController onscreen so do something otherwise do nothing
}
Also don't hardcode the bounds of the device's screen. Use the following to find your screen size (in points):
CGRect screenBounds = [[UIScreen mainScreen] bounds];
Hope this helps.

iOS Universal App - Access different Nibs for iPad and iPhone

I am writing my first universal app, I have converted my nibs so that there are iPad and iPhone versions.
The iPad version is in the Resources-iPad folder and called 'InfoViewController-iPad.xib'. The iPhone version in the main folder and called 'InfoViewController.xib'
I have the following action to show the relevant xib
-(void) touchesBegan: (NSSet *) touches withEvent: (UIEvent *) event {
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
infoViewController = [[InfoViewController alloc] initWithNibName:#"Resources-iPad/InfoViewController-iPad" bundle:nil];
}
else
{
infoViewController = [[InfoViewController alloc] initWithNibName:#"InfoViewController" bundle:nil];
}
infoViewController.delegate = self;
infoViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentModalViewController:infoViewController animated:YES];
[infoViewController release];
}
When this runs on the iPhone it works fine, but it crashes when run on the iPad.
Any help would really be appreciared
You do not need to put the folder name in the nib name for the iPad version, it will be found as long as it has a different name than the iPhone version.
If removing the folder from the initWithNibName doesn't work for you, please edit your question and post the results of the backtrace from the console.
You should not need the Resources-iPad/ prefix on the name of the iPad nib. iOS knows how to find resources in your bundle. The folder hierarchy you see in Xcode is simply for organizing files and for the developer's benefit.

How to convert an iPhone app to an iPad app

I am a beginner, and I have an iPhone app.
I want to convert iPhone app to iPad app.
I want to increase the size of all control, images and views according to iPad dimensions programmatically as I have no controls in XIB but in fact they are programmatically made.
I don't want to change the dimensions manually at every place because it is too much of a cumbersome work.
Is there any way I can do this in a better way?
The simple answer is NO.
You have to do it manually. There is no automatic system.
That is the correct answer.
if you have an absolutely trivial app - ie, with no images or controls or layouts! - you can of course just change it to an iPad app.
The questioner is asking specifically how to change all the images, layouts, and so on in a normal app. The answer is it must all be done completely manually. There is no automatic system for re-doing design or re-doing images in Photoshop, etc.
Note that similarly if you want to do both portrait and landscape layouts of an app, you or your designers have to of course simply design both layouts. There's no, say, "artificial intelligence" system that automatically does art direction for the app! You simply have to manually design both layouts and manually build in Photoshop all necessary images for each situation. The same applies to iPad v. iPhone.
(Note that sometimes you will have to do four totally different layouts, and sets of graphics .. for the phone/pad and portrait/landscape.)
This is exactly why iPad apps are sometimes labelled "HD" in the app store - they are of course totally different.
In Xcode, click on your project on the "Groups & Files" sidebar. Press command-I. Search for Targeted Device Family and change it from iPhone to iPad. Then it will compile and run on an iPad but the UI might look a bit funky.
What I did after that was open the xib I used for my iPhone app's FlipSide view (the one that looks funky on the iPad) go to File->Create iPad version and save it as FlipSideiPad.
Then when I load the view controller, I used the following if statement to tell my program to load the iPhone interface if the device is an iPhone or to load the iPad interface if the device is an not an iPhone.
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
{
FlipsideViewController *controller = [[FlipsideViewController alloc] initWithNibName:#"FlipsideView" bundle:nil];
controller.delegate = self;
controller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:controller animated:YES];
[controller release];
}
else
{
FlipsideViewController *controller = [[FlipsideViewController alloc] initWithNibName:#"iPadFlipsideView" bundle:nil];
controller.delegate = self;
controller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:controller animated:YES];
[controller release];
}
I hope that helps.
You need to resize the view manually...there is no such single methods for converting iphone app to ipad

How to switch between different classes in an universal iPhone / iPad app?

I have a special class that manages gestures and other things. It is strongly targeted towards iPhone. On the iPad, I need a 90% different behavior of that class, so I want to split MyController into MyController_iPhone and MyController_iPad.
How would I alloc-init the appropriate class depending on if it's the iPad or iPhone?
You can do something along the following lines:
MyController *controller = nil;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
controller = [[MyController_iPad alloc] init];
} else {
controller = [[MyController_iPhone alloc] init];
}
You might want to subclass the controller for, say, the iPad. When you push/present it, check to see which platform you're on, and if you're on iPad, present the iPad subclass, with the modified behavior. You can use the UI_USER_INTERFACE_IDIOM() macro determine which device you're on.