Here is my question :
I have an app running smoothly on iOS 3.0
I've been working a long time to port it to 4.0 and to include the new features.
I added iAds using Interface Builder.
I know that I have to define it programmatically to still support 3.0 devices.
I weak linked the framework. But the app crashes when loading the NIB.
Is there a way to load NIB's depending on the firmware version ?
Let's say I have FirstView.xib and FirstView3X.xib
How can I choose which one will be loaded depending on the firmware ?
Thanks
PS: It's my first question on StackOverflow !
Congratulations to your first question :-) How do you load the nibs? It’s a good idea to split the interface into several files. I usually use a separate nib per every controller and load them using the initWithNibName:bundle: initializer. Since you supply the nib name here, you could easily customize the loading behaviour.
If you load the nibs using the tab bar controller, you probably have all the tabs in one nib. I think I would break the tabs into separate nibs and load them programmatically:
id tab1 = [[UIViewController alloc] initWithNibName:#"Tab1" bundle:nil];
id tab2 = [[UIViewController alloc] initWithNibName:#"Tab2" bundle:nil];
id tab3 = [[UIViewController alloc] initWithNibName:#"Tab3" bundle:nil];
[tabBarController setViewControllers:[NSArray arrayWithObjects:
tab1, tab2, tab3, nil]];
And since you would now have the control over the nib names, you could easily detect the firmware version and load the correct nib:
id tab1 = [[UIViewController alloc] initWithNibName:
[self nibNameForCurrentFirmware] bundle:nil];
As for the firmware version detection itself, I think you could use [UIDevice systemVersion].
You can pull the current version from the UIDevice object:
NSString *osVersion = [[UIDevice currentDevice]systemVersion];
NSArray *ver = [osVersion componentsSeparatedByString:#"."];
If you're happy with comparing strings for single values (e.g. [[ver objectAtIndex:0] isEqualToString:#"3"]). You might want to convert the version numbers to integers so you can compare them for range (e.g., osMajor >= 4).
You can also check for certain classes to exist and load the appropriate NIB based on that:
if (NSClassFromString(#"MKMapView") != nil) {
/* Do map stuff... */
}
Related
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.
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;
}
[...]
}
I have a UINavigationController that displays several buttons on screen. They all simply use the line:
myViewController *newView = [[myViewController alloc] initWithNibName:#"myViewController"
bundle:nil];
[[self navigationController] pushViewController:newView animated:YES];
to transition to the next view. I have one such view controller however that results in a crash at this very line ONLY on iOS 5. It works perfectly fine on iOS 6. I am baffled. There are no real details to the crash. It is a SIGABRT that highlights the main.m line:
exitStatus = UIApplicationMain( argc, argv, nil, NSStringFromClass([ApplicationDelegate class]));
I have no clue...
You Need to unCheck the Auto Layout.
And make sure you are changing here also.. select ios 5.1
Try this line:
myViewController *newView = [[myViewController alloc] initWithNibName:#"myViewController"
bundle:[NSBundle mainBundle]];
in place of:
myViewController *newView = [[myViewController alloc] initWithNibName:#"myViewController"
bundle:nil];
I have experimented a similar issue an here are the steps that I feel need to be considered:
(if you are using xib file) like Venkat Manohar Perepa mentioned, check that Use Auto Layout is turned off as it is an iOS 6 specific feature.
(if you are using xib file) look at the content of the xib file that is used when presenting your viewcontroller and check that there is no class that are iOS6 specific (e.g: NSLayoutConstraint)
Last (and that was the issue I was facing) you should check if the crash appear on a device that has iOS5 installed. If it doesn't but still crash on the simulator remove the application you have installed by choosing iPhone Simulator > Reset Content and Settings.
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.
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.