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

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.

Related

Auto-resize iPhone xib app to ipad

I built an iPhone app "using xib" with 5-6 screens. Now I want to auto-resize the display for iPad. I am using xcode 4.6.
Do I have to rebuild the entire code using storyboards? It will be a very tedious work. Is there any solution for this?
You'll need to create only new xib files for iPad and name them as ViewController_iPhone.xib and ViewController_iPad.xib and when switching your views, just put a simple condition
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad){
ViewController *viewController = [[ViewController alloc] initWithNibName:
#"ViewController_iPad" bundle:nil];
} else {
ViewController *viewController = [[ViewController alloc] initWithNibName:
#"ViewController_iPhone" bundle:nil];
}
use autolayout and everything will be done automatically
if not autolayout, then making 2 xib will be a better option. Make ipad size xib with the same name and put ~ipad after classname.
Like if you xib name is myClass.xib and create other one like myClass~ipad.xib.

upgrading iPhone app to universal and now using splitview

I have an iPhone app that works and is getting used. I now want to upgrade this application to a Universal app. Taking that into consideration I've already made changes, like creating another MainWindow.xib for the iPad, which i've gotten to work. I've pretty much got the whole iPhone App working for the iPad. The next step I needed to take was to convert my Events Calendar to be a splitview. As far as I can tell, I'm don't need to change any of the logic in the two controllers I already have (CalendarViewController and CalendarDetailViewController).
That being said, what is the best way to make them work on a splitview? Is it possible to have the splitview use these two controllers (since a splitview has two controllers by default, a TableViewController and a ViewController)? Would I then need to create another appDelegate or something to pass all the right information back to the MainWindow.xib? Or am I going to need to create a new SplitViewController? and if so, how would I then combine all the logic from my two Calendar Controllers?
Any help would be greatly appreciated!!
Assuming you are using StoryBoard: drag a SplitViewController into the iPad StoryBoard. Also be sure your two desired UIViewControllers are in there. Control-click on the SplitViewController and drag over to each UIViewController and select you how want it set.
I know it's a bit late to answer this question but if someone needs...
You donĀ“t need another appDelegate, you just need to check (in appDelegate) whether your device is an iPad, and then set an array of view Controllers with the MasterVC and the DetailVC. Otherwise you will set your rootViewController as you are doing now in the iPhone app.
It would be something similar to that:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[...]
YourMasterVC *mvc =
[[YourMasterVC alloc] initWithStyle:UITableViewStylePlain];
UINavigationController *masterNav =
[[UINavigationController alloc] initWithRootViewController:mvc];
YourDetailVC *dvc = [[YourDetailVC alloc] init];
cvc.detailViewController = dvc;
if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) {
// On iPad
UINavigationController *detailNav =
[[UINavigationController alloc] initWithRootViewController:dvc];
UISplitViewController *svc = [[UISplitViewController alloc] init];
svc.delegate = wvc;
svc.viewControllers = #[masterNav, detailNav];
self.window.rootViewController = svc;
} else {
// On iPhone
self.window.rootViewController = masterNav;
}
[...]
}

iOS equivalent to Android Fragments/Layouts

In Android you can use Fragments to develop only one app targeted to phones and tables, so you can have different UI. You can even use only Layouts and have some condition on the code to run tablet or phone logic.
I need to develop an app for iPhone and iPad and I wonder if there is something similar for implementing different UIs and slighty different behavior. In my case the iPhone app would use tabs at the bottom of the screen, but the iPad one should use the menu on the left side.
Yes you can use Different UI for iPhone and iPad.
Create Two XIB files and when showing them on the screen use this condition to initiate the XIB
UIViewController *viewController;
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
viewController = [[[ViewController alloc] initWithNibName:#"ViewController_iPhone" bundle:nil] autorelease];
} else {
viewController = [[[ViewController alloc] initWithNibName:#"ViewController_iPad" bundle:nil] autorelease];
}
[self.navigationController pushViewController:viewController animated:YES];
UIViewController and XIB, respectively.
Also see Creating a Universal App.

Cocoa - Need help in switching xibs

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.

How to make iPhone and iPad version of an app?

I am trying to make an app which works on both iPhone and iPad. I am looking how to make an interface compatible on both. When the app loads I am displaying a table view. How can I load different nibs based on device? I am using this to switch between nibs.
if ([[UIDevice currentDevice] respondsToSelector:#selector(userInterfaceIdiom)])
{
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad)
{
device = #"iPad";
}
else
{
device = #"iPhone";
}
}
But in MainWindow.xib it says view is loaded from the view controller for iPhone. Can I make this dynamic based on device? ie I want to show from the start of app different nibs based on device.
Thanks.
Actually, Apple does all this automatically, just name your NIB files:
MyViewController~iphone.xib // iPhone
MyViewController~ipad.xib // iPad
and load your view controller with the smallest amount of code:
[[MyViewController alloc] initWithNibName:nil bundle:nil]; // Apple will take care of everything
You can do that in a similar way:
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad){
mainMenu = [[MainMenu alloc] initWithNibName:#"MainMenuiPad" bundle:nil];
}else{
mainMenu = [[MainMenu alloc] initWithNibName:#"MainMenu" bundle:nil];
}
For making universal app,
1-set target family in info build tab for app as iPhone/iPad.
2- Delete window from main window.
3- Add two xib one for iPhone and one for iPad(by selecting iPad xib).
4- make appDelegate class as controller file for these xib's.
5- Add window on these xibs and view controller or navigation controller and by IB Inspector set load nib name and controller file here which one is your first view.
6- And then make differnet xib for iPad and iPhone which having tableview or other controls.
7-Make single contoller file or different controler file for different device for same you need to check the device by this if else condition
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad){
8-Now you need to load xib in appDelegate class in method didFinishL--
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad){
// load your nib for iPad here which having view controler or navigation controller as well window.
}else{
//load nib for iPhone.
}
Try this in your Info.plist:
Main nib file base name [NSMainNibFile]: MainWindow_iPhone
Main nib file base name (iPad) [NSMainNibFile~ipad]: MainWindow_iPad
I hope this helps you.