9
votes

I was wondering if anyone would be able to tell me, starting a new app from scratch, how would I organise having a universal (iPhone/iPad) iOS app. I noticed using the default template with the Xcode Beta, it gives you both a shared AppDelegate and subclassed appdelegates for iPhone and iPad.

Now, how do you put in the logic to determine which app delegate to use, how does it know which one to instantiate and work with as the default template doesn't state. If I were to write in the iPhone appDelegate, how do I know that this will only run for the iPhone iOS for example?

5
if you are discussing the XCode Beta, I believe that is under NDA.. but this question might help stackoverflow.com/questions/2862537/…Aaron Saunders
Its not an xCode Beta specific question so ignore I mentioned that.Doz

5 Answers

13
votes

The Info.plist ("Main nib file base name") for an app specifies a main window .xib file to load, and that .xib file specifies an app delegate and root window controller for the app.

The Info.plist for an iPad ("NSMainNibFile~ipad") additionally specifies a main window .xib file for the iPad, which can contain a different app delegate and a different root window controller for the app. Or they could be the same ones, using runtime UIUserInterfaceIdiomPad checks.

The runtime, which knows what device type on which it's running, picks the correct initial .xib file to load from the info.plist, and from there you get the correct app delegate and root window controller configured and running.

9
votes

Use following code

id<UIApplicationDelegate> delegate = [[UIApplication sharedApplication] delegate]; 
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
    AppDelegate_iPad *appDelegate = (AppDelegate_iPad *) delegate;
else
    AppDelegate_iPhone *appDelegate = (AppDelegate_iPhone *) delegate;

whenever you are required to access to the delegate.

2
votes

Variations on a theme

Create a Common.h file

// Global Helpers
#define APP_DELEGATE()  (AppDelegate *)[[UIApplication sharedApplication] delegate]
#define APP_DELEGATE_IPAD()  (AppDelegate_iPad*) [[UIApplication sharedApplication] delegate]; 
#define APP_DELEGATE_IPHONE()  (AppDelegate_iPhone*) [[UIApplication sharedApplication] delegate]; 
#define IS_IPAD ([[UIDevice currentDevice] respondsToSelector:@selector(userInterfaceIdiom)] && [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad)

Import this Common.h / AppDelegate_iPhone.h / AppDelegate_iPad.h /AppDelegate.h in your precompiled header .pch file

then in your class you can simply call

if (IS_IPAD) {
      AppDelegate_iPad *appDelegate = APP_DELEGATE_IPAD();
}else{
    AppDelegate_iPhone *appDelegate = APP_DELEGATE_IPHONE();
}
1
votes

I am doing the same thing at the moment and I learned a lot from the following tutorial:

http://iphonedevelopment.blogspot.com/2010/04/converting-iphone-apps-to-universal.html

This has helped me out to setup the project to support iPad and iPhone devices.

1
votes

Continuing on Sagar's answer, here is code that will fix Ryan Waggoner's comment.

id<UIApplicationDelegate> delegate = [[UIApplication sharedApplication] delegate]; 
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
    delegate = (AppDelegate_iPad *) delegate;
else
    delegate = (AppDelegate_iPhone *) delegate;

The problem with the previous answer is that it doesn't actually give access to the variable delegate outside the IF statement. This code simply casts the original variable to the proper type.