Making an iPad nib load in a universal app - ios

I've set up a BOOL called isUsingiPad to detect when my user is using an iPad. I used this to do so:
UIDevice* userDevice = [UIDevice currentDevice];
if (userDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad) {
isUsingiPad = YES;
}
When my application first starts, it checks to see if the device being used has gone through my registration. If it has then it sends the user to the main View Controller of my app. However... when a registered user (that is using an iPad) registers, closes the app, then re-opens it, they are sent to the iPhone nib instead of the iPad. I have 2 nibs for each view in my app. One for iPhone and one for iPad. There is a single View Controller controlling each set of 2. I have already put in place the code to handle whether it's an iPhone or an iPad. My question is this: What should I add to make sure that a user gets to the iPad nib every single time? Where do I add this? I can edit this question to include any code necessary. Thanks in advance.
Edit: Updated -(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: method.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
UIDevice* userDevice = [UIDevice currentDevice];
if (userDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad) {
isUsingiPad = YES;
}
if (!isUsingiPad) {
self.viewController= [[PassportAmericaViewController alloc] initWithNibName:#"PassportAmericaViewController" bundle:nil];
} else {
self.viewController = [[PassportAmericaViewController alloc] initWithNibName:#"PassportAmericaViewController-iPad" bundle:nil];
}
self.window.rootViewController = self.viewController;
[self.window addSubview:navigationController.view];
[self.window makeKeyAndVisible];
return YES;
}

This is what Apple uses in the app templates to achieve this, it is implemented in your AppDelegates applicationDidFinishLaunchingWithOptions:
Now making sure that your user is returned to the correct screen every single time, depending on your setup you may want to initialize this in viewDidLoad or viewDidAppear.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
self.viewController = [[ViewController alloc] initWithNibName:#"ViewController_iPhone" bundle:nil];
} else {
self.viewController = [[ViewController alloc] initWithNibName:#"ViewController_iPad" bundle:nil];
}
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}

In order to dynamically load nibs for iPad/iPhone in universal applications you should use the following naming conventions:-
iPhone - MyNibName.xib
iPad - MyNibName~ipad.xib
Doing it this way you do not need to do any manual loading or if statements.

Related

Where do I check if user have already logged in when app starts?

I need to know that so I won't push home UIView Controller (where users decide to log in or create a new account) but the App UIview Controller per se.
If fetching from CoreData, you can put it in the AppDelegate to determine the first view controller.
// Following method intimates us the application launched successfully
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:
[[UIScreen mainScreen] bounds]];
// ***perform CoreData fetch here***
NSString *nibName;
if (/* created acct already */) {
nibName = #"acctCreatedNib";
}
else {
nibName = #"createNewAcctNib";
}
// Override point for customization after application launch.
self.viewController = [[ViewController alloc] initWithNibName:nibName bundle:nil];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}

Instantiating UITableViewController in AppDelegate to work with Storyboard iOS

Need help with a "Application windows are expected to have a root view controller at the end of application launch" warning in my console when running my app. It's a core data test I am working on. I am not getting the NSLog statements I am using for testing, only the previous message.
I created a new project from an Empty Application. My app delegate didFinish method code was generated to look like this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
I added a storyboard and set it as the Main Interface. Then added a UITableView to the storyboard. Created a UITableViewController by adding a file and set it as the UITableView's class in the identity inspector.
It seems to get rid of the warning I should set the rootViewController. How do I set my UITableViewController as the rootViewController if I did not instantiate it in the appDelegate.m file? Alternately, If I do instantiate it in the appDelegate.m like so
UITableViewController *tableViewController = [[UITableViewController alloc]init];
self.window.rootViewController = tableViewController;
how do I associate tableViewController with corresponding .h and .m files?
Using Xcode 5.0.1, deployment target 7.0
When you add a storyboard to your empty application, and set the property "Main Storyboard file base name" in your Info.plist as the name of your storyboard, then the application instantiates your "window" object and assigns an instance of your storyboard's "initialViewController" as the "rootViewController" property of your window object. So you don't see the warning :
"Application windows are expected to have a root view controller at the end of application launch" when you do :
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
return YES;
}
This works fine.
However, in the code :
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]
//Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
If you were using storyboards, you have overridden default behaviour by creating a new window object, which no longer has the rootViewController provided by storyboard. In this case, you have to explicitly add a root view controller to your window object.
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
UIStoryboard* storyboard = [UIStoryboard storyboardWithName:#"YourStoryboard" bundle:[NSBundle mainBundle]];
YourTableViewController* vc = (YourTableViewController*)[storyboard instantiateInitialViewController];
_window.rootViewController = vc;
[self.window makeKeyAndVisible];
return YES;
}
Hope this helps !!
In StoryBoard set the desired controller as initialViewController.
In AppDelegate.m
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
youRootViewControllerObject = [storyboard instantiateInitialViewController];
This way you can access YouRootViewController class.
I did a lot of research and finally found out the right way to do this
in appDelegate.m instead of
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
The code should simply be
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
return YES;
}
See Sitepoint's helpful page for more detailed information
http://www.sitepoint.com/ios-application-development-storyboards/

How to load different view controllers based if URL is provided on start in iOS

I have an app, it authenticates with Instagram using safari, and when it returns I want it to load table view right away, without the login view.
Here is what I do now:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
DVGViewController *myVC = [[DVGViewController alloc] initWithNibName:#"DVGViewController" bundle:nil];
self.viewController = [[UINavigationController alloc] initWithRootViewController:myVC];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
// some code skipped
UITableViewController *myTVC = [[DVGTableViewController alloc] init];
self.viewController = [[UINavigationController alloc] initWithRootViewController:myTVC];
return YES;
}
At the moment I still get first method to work every time, although second method is triggered too, since I get calculations from url with it and I know that. Why it doesn't load tableView I don't know.
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
method will call if you app is come fro m specific URl like from facebook auth or from safari then this method will call
I have found an error. In second method I have never set window and rootViewController. Adding this code to second method helped.
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];

MainWindow.xib for ipad and iphone

I am trying to build on this demo which contains both a MainWindow.xib and a ImageManipViewController.xib . But my app contains the following code in the AppDelegate.m and my app does not (yet?) contain a MainWindow.xib. Is it better/best for me to add 2 MainWindow.xib files (one for iPhone and one for iPad) too (that are called in my method, each calling its own xib file) or is are the MainWindow.xibs just extra?
(Btw, if it turns out that the answer is that the MainWindow.xibs are redundant, then can you say why it might have been used in the original demo? Was it likely just a result of the author simplifying the steps in creating the demo, for example?) I have not found a way to contact the author directly.
If there is a better approach to developing a "universal" app, please advise me.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
self.viewController = [[BSViewController alloc] initWithNibName:#"BSViewController_iPhone" bundle:nil];
} else {
self.viewController = [[BSViewController alloc] initWithNibName:#"BSViewController_iPad" bundle:nil];
}
self.window.rootViewController = self.viewController;
You can build your main window and its attached subviews (and even view controllers) either programmatically or by using a Xib file. The result is the same, but small demo projects often use Xib files in order to simplify the code and focus on the part that they want to show you.
Two Xibs, one for iPad and one for iPhone is perfectly fine because iPad apps are encouraged to use views that make the most of the iPad large screen; for this reason, keeping them as separate files is recommendable. Your model and controllers should be common to iPad and iPhone, though.
And about loading Xibs, if your project is targeting iOS 4.0 or newer, you can name your xib files "BSViewController~iphone.xib" and "BSViewController~ipad.xib" and avoid some conditionals in your code:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.viewController = [[BSViewController alloc] initWithNibName:#"BSViewController" bundle:nil];
self.window.rootViewController = self.viewController;
}

No User Interface file created with iOS Project

I am getting started with iOS programming, and created a new project in XCode 4.2.1. However, I do not see .xib file in my project as expected. I tried added a new .xib file and build interface on it, but when I run my program, I see a blank white screen on the iPad Simulator. Am I missing something? Thanks.
You can replace this method in the appDelegate (and the name of the xib / strip out universal aspects of code if needed)
- (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;
}
or
choose a Single View Application from the templates you are offered when creating a new app

Resources