iOS Universal App - Access different Nibs for iPad and iPhone - 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.

Related

UIKit NIB not loading in bundle

NSInternalInconsistencyException', reason: 'Could not load NIB in bundle: 'NSBundle </Users/quantum/Library/Application Support/iPhone Simulator/6.1/Applications/19503C82-22E2-4787-A4F5-8D83EDD5D58B/foo.app> (loaded)' with name '_UIDocumentActivityViewController''
I'm creating a QLPreviewController, presenting it to show a PDF. I then tap the share button. It crashes.
I downloaded Apple's Document Interaction example project. I put my PDF fetching class into there, fetched a PDF, display it.. and it works. No crash on the share button. Both are for targets 6.1. I tried setting Apple's code to target iPad only like my project. Their code works, mine doesn't, and I'm baffled. From the error message it sounds like a bug in the SDK but I can't pinpoint it.
Have you seen this before?
QLPreviewController *previewController = [[QLPreviewController alloc] init];
[previewController setDataSource:self];
[previewController setDelegate:self];
[self presentViewController:previewController animated:YES completion:^{}];
#pragma mark QLPreviewControllerDataSource
- (NSInteger) numberOfPreviewItemsInPreviewController:(QLPreviewController *)controller {
return 1;
}
- (id <QLPreviewItem>)previewController:(QLPreviewController *)controller previewItemAtIndex:(NSInteger)index {
return [NSURL fileURLWithPath:self.pdfPath];
}
I tried removing the reference to the framework, deleting derived data, cleaning the project, readding the QuickLook framework. I did show in Finder in both Apple's project & mine & they have the same path.
And same thing occurs when I use a UIDocumentInteractionController.
That little overlay with the email/print etc options is not loading in my project.
Apple support provided me with the answer.
I had over ridden an init method in a category and this screwed up the class initialization.
Moral: don't override init in a category method.
just try for initwithnib
QLPreviewController *previewController = [[QLPreviewController alloc] initWithNib: (QLPreviewController) bundle : nil];
hopefully it works.
if you have used NavigationController then use:
QLPreviewController *previewController = [[QLPreviewController alloc] init];
[self.navigationController pushViewController:previewController animated:YES];
else
QLPreviewController *previewController = [[QLPreviewController alloc] init];
[self presentModalViewController:previewController animated:YES];
According to Apple's documentation QL generators should not have NIB files as resources.
Although a Quick Look generator does not (and should not) have nib files as resources, you can add other resources if necessary.

App wont start using testflight on iOS6

I have an application that I want to test it on iOS device. The application uses NIB files and no story board.
Target framework is set to - 5.1
Device - Universal.
I have created the IPA file and uploaded to TestFlightApp.
I have downloaded and installed the application on my iPad. Weird thing is when I tap on the icon a black screen shows and nothing else happens.
I have done the following settings.
Main Interface - SSDMainViewController
Main Storyboard - Not set as I don't have any storyboard in the applicaion.
It is not the problem of IOS versions as other apps are working fine.
EDIT : When I double click the iPad button I saw that the application
is not crashing. It is running in the background.
EDIT 2 : More information on the question.
Well I have taken a view based application and it has all NIBs no storyboard. It was initially an iPhone application targeting the IOS 5.1 but then I have changed the value from the project drop down to UNIVERSAL. But that I think is no problem because when I installed it in my iPad it showed me nothing. Also it showed black screen with the iPhone frame and then nothing. The application is still live in the thread.
What bothers me is that I have done this in the AppDelegate :
I have set the
self.mainViewController = [[SSDMainViewController alloc] initwithnibname:#"SSDMainViewController" bundle:nil];
And then I have set the navigation controller and then pushed the view to it.
I FOUND SOME MORE INFORMATION
In the console it says.
The application is expected to have its root view set at the end of application start.
MY APP DELEGATE
ftipValue=0.25;
cardtype = #"American Express";
[cardtype retain];
[self CallFunctionForLogout];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Create an instance of YourViewController
//SSDMainViewController *yourViewController = [[SSDMainViewController alloc] init];
self.mainViewController = [[[SSDMainViewController alloc] initWithNibName:#"SSDMainViewController" bundle:nil] autorelease];
// Create an instance of a UINavigationController
// its stack contains only yourViewController
UINavigationController *navController = [[UINavigationController alloc]
initWithRootViewController:self.mainViewController];
navController.navigationBarHidden = YES;
// Place navigation controller's view in the window hierarchy
[[self window] setRootViewController:navController];
[self.window makeKeyAndVisible];
return YES;
Please use two xib file, universal app we want two xib (nib)
one for iPhone - ViewController_iPhone
second for for iPad - ViewController_iPad
Add following code to your AppDelegate.m file.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
{
self.viewController = [[[ViewController alloc] initWithNibName:#"ViewController_iPhone" bundle:nil] autorelease];
}
else {
self.viewController = [[[ViewController alloc] initWithNibName:#"ViewController_iPad" bundle:nil] autorelease];
}
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
I have done this and it's work fine for me.
That error means that you're not setting up your application correctly.
You say you've set SSDMainController as the main interface file - is this both for iPhone and iPad? There are two sets of entries in that section of the summary tab for universal apps.
I would expect a different xib file to be specified for the iPad, since a different sized view and different layout would be in use.
You have either not set the iPad xib, so the app can't set up a window with root view controller, or you haven't set up a valid iPad xib, so it isn't loading at all, with the same results.
If you just want the app to run in the mini-iPhone window with the 2x button, leave it as an iPhone only app.
If you are getting "The application is expected to have its root view set at the end of application start." there are a number of possibilities. Clearly, that is the problem, since you have a black screen with nothing in it...
Check out this SO question: Application windows are expected to have a root view controller at the end of application launch warning Rob Mayoff has a good description of what should be happening when your application initializes.
Also, linked to in the above post, is this post wherein there are an additional 35 answers with various scenarios of what could be happening.
Beyond browsing through those links, you will need to post up additional code and/or descriptions of how your nibs are wired up for anyone to help you--as evidenced by the myriad ways it is possible to cripple the initialization sequence.

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.

Loading xib dynamically but wrong one displaying

I have an universal app that I am trying to share a viewController code with. I have this:
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
AboutController *screen = [[AboutController alloc] initWithNibName:#"iPhoneAboutController" bundle:nil];
screen.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentModalViewController:screen animated:YES];
}
else
{
AboutController *screen = [[AboutController alloc] initWithNibName:nil bundle:nil];
screen.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentModalViewController:screen animated:YES];
}
Although this is loading, and when I step through the code, it does hit the xib for the iPhone but it seems to always be loading the iPad version. I know this because in the xib file for the iPhone, I have manually added different background images and it never shows. In the iPhone simulator it shows the iPad version where it is off screen.
Also, if I step through the code in the controller, it does show that the load is the iPhone yet display is all iPad objects. In the iPhone xib, I do have the Files Owner set to the AboutController.
This is the first time I am attempting to "share code". I know I can just create separate class files with the same code but this seems senseless. Any help is greatly appreciated.
Geo...
For starters: make sure you don't override nib initialization in your AboutController.
If not, try cleaning your project (also delete your app's folders in ~/Library/Developer/Xcode/DerivedData). Also uninstall the app from device and then rebuild.

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.