I need localization to be independent of device (iPad) setting.
Is it possible to switch between localized storyboard in code. I found out how to change the NSUserDefaults or create new NSBundle so I can get the correct localized strings. But what if I have lokalized storyboards how should I handle that?
thanks for any suggestions
If you want to load another storyboard than the default one (the main storyboard), just load it:
UIStoryBoard *storyboard = [UIStoryboard storyboardWithName: #"TheOtherStoryboard" bundle: nil];
UIViewController *rootVC = [storyboard instantiateInitialViewController];
If you don't specify a main storyboard/NIB in your Info.plist file, you can also load the storyboard manually in the application:didFinishLaunchingWithOptions: method of your application's delegate. In fact, you must do it there if you don't specify a main storyboary/NIB.
Hope that helps. :-)
Related
I am trying to access the initial viewcontroller of my storyboard. It is a navigation controller which is wired up to a second viewcontroller via a seque. So after my application did finish launching I want to directly show the viewController that is connected through the segue. I tried it out with code like this but it doesn't work ...
UINavigationController *navController = (UINavigationController*)self.window.rootViewController;
[navController.topViewController performSegueWithIdentifier:#"showLoginScreen" sender:self];
What am I doing wrong?
4 years later:
If I look at my question again after 4 years, I honestly have no idea what my real problem was.
Be sure you have tick marked the
is initial ViewController
option for UINavigationController in storyBoard
UIStoryboard* storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
UINavigationController * myStoryBoardInitialViewController = [storyboard instantiateInitialViewController];
Sebastian, I'm not sure why you would want to start the initial view controller manually - all my projects (which all use storyboards) do this automatically if you ticked "Use Storyboards" on the second screen in the "New Project" wizard.
Maybe you need to mark the storyboard scene as inital? This can be done in the scene's attribute inspector by ticking the "Is Initial View Controller" - rather obviously named.
And then - if you really have a unusual setup which requires you to access the scenes manually, you can use the following:
UIStoryboard *sb = [UIStoryboard storyboardWithName: "StoryboardName"
bundle: [NSBundle mainBundle]];
UIViewController *vc = [sb instantiateInitialViewController];
(Beware - no code completion here, so check spelling again.)
Or maybe I am getting your question completely wrong..? Happy hacking!
In my app i have tabBar
UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
TabBarController *tabBar = [storyBoard instantiateViewControllerWithIdentifier:#"TabBarController"];
_window.rootViewController = tabBar;
Ok, here is a reason in the year 2022 pre SwiftUI apps. Your apps starts... it has several choices, one, it wants you to login, two it wants you to sync with home base, and three everything is fine and just show the main UI. Case two may refresh a rather large body of information before you build out you main UI.
I'm wondering if someone could explain (or point me in the right direction)
where the code for instantiating UIWindow disappears to when NOT using storyboards? In the empty-application project template the window is created in application didFinishLaunnching... in your AppDelegate.
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
However if using storyboards, the above code is omitted, though obviously UIApplication knows which window to start off with.
Where the application looks for the info.plist file to know which storyboard(s) to start off with.
I'm certain this is all well documented somewhere I just haven't found it. Read this Where is the UIWindow instantiated in an iPhone app? but not much help. I've been at iOS for awhile, just never had to mess with the initial startup of an app until now. Thanks
I think you meant 'where the code disappears to when you are using storyboards.'
The application loads the storyboard according to the "Main storyboard file base name" (UIMainStoryboardFile) key in your Info.plist, and from that storyboard it loads the view controller with the "Is initial view controller" toggle set.
Edit: As asked in the comments, the following code (similar to the initial loading in xib-based apps) will allow you to load and display a storyboard by name upon application launch:
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"StoryboardName" bundle:nil];
UIViewController *viewController = [storyboard instantiateInitialViewController];
self.window.rootViewController = viewController;
[self.window makeKeyAndVisible];
return YES;
}
While using storyboards, the storyboard to be loaded comes from your app's Info.plist file.
There will be a section in your Info.plist file with the key value pair like this:
<key>UIMainStoryboardFile</key>
<string>MainStoryboard</string>
In this case, MainStoryboard is the name of the default storyboard that is loaded.
I call a View to be presented with the following code:
#import "infoView.h"
...
infoView *viewInfo = [[infoView alloc] initWithNibName:nil bundle:nil];
viewInfo.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:viewInfo animated:YES];
But when it is presented in run-time the view that is loaded turns out black.
Currently I am using storyboard, but I need to use this code, for it is a lot more efficient in my case, because I am dealing with multiple views!
It works fine if I connect it via StoryBoard.
I should be seeing 2 labels, 1 UITextView, and 2 UIButton.
The view was created using StoryBoard, when the .m and .h files for the view where created I did not add a .xib for it. And also it is linked through the "Custom Class" section in StoryBoard.
Thanks, hope someone can help!
It's generally pretty bad form to mock people who are taking the time and effort to help you.
Naming is important it makes your code easier to work with and allows other people to use it. Not following the conventions for the language you are working in is dangerous and means that your code is not compatible with other developers as things are interpreted differently.
If you look at the docuemntation for UIViewController you'll see this note in the initWithNibName:bundle: method description
If your app uses a storyboard to define a view controller and its associated views, your app never initializes objects of that class directly. Instead, view controllers are either instantiated by the storyboard—either automatically by iOS when a segue is triggered or programmatically when your app calls the storyboard object’s instantiateViewControllerWithIdentifier: method. When instantiating a view controller from a storyboard, iOS initializes the new view controller by calling its initWithCoder: method instead. iOS automatically sets the nibName property to a nib file stored inside the storyboard.
Therefore you are instantiating your controller wrong, the storyboard should be instantiating it. Which is done like this (naming corrected)
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:[NSBundle bundleForClass:[self class]]];
InfoViewController *infoViewController = [storyboard instantiateViewControllerWithIdentifier:#"InfoViewController"];
infoViewController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self infoViewController animated:YES];
Side note
infoView is a bad name for the class not only because you didn't start with a capital but also because it's completely deceiving. Anyone reading this would assume that InfoView is a subclass of UIView not UIViewController.
I'm programming a complex storyboard application and I'm encountering some issues when it comes to code re-use across view controllers and different application paths.
Can I segue to a ViewController that is not directly connected to the current one?
How do I segue out from a button to several ViewControllers conditionally? Connecting both does not work.
Can I enter the ViewController sequence from an arbitrary position in the application?
Just a few questions that come up. Anybody have any ideas or good examples?
Can I segue to a ViewController that is not directly connected to the current one?
Not with a segue. But you can push or present a viewController from a storyboard modally, like you did with .xib files.
// if self was created from code or from a .xib:
UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:#"MainStoryBoard" bundle:nil];
// if self was instantiated from within a storyboard:
UIStoryboard *storyBoard = self.storyboard;
MyFancyViewController *viewController = [storyboard instantiateViewControllerWithIdentifier:#"MyFancyViewControllerIdentifier"];
[self presentModalViewController:viewController animated:YES];
But you have to set the identifier first. Select the viewController in the storyboard and do that in the attributes inspector.
Once the MyFancyViewController is visible you can use all its segues. It might feel strange to switch between code and storyboard segues, but there is nothing wrong with that. It makes the whole storyboard thing really usable.
How do I segue out from a button to several ViewControllers conditionally? Connecting both does not work.
Add two or more segues that start from the viewController (not from a button or any other view. E.g. start your control-drag at the statusbar) to the target viewControllers. Set identifiers for them and use some code like this:
if (someState) {
[self performSegueWithIdentifier:#"MyFirstSegueIdentifier" sender:somethingOrNil];
}
else {
[self performSegueWithIdentifier:#"MySecondSegueIdentifier" sender:somethingOrNil];
}
Can I enter the ViewController sequence from an arbitrary position in the application?
Yes, if you use "old school" view controller management. Similar to the first part. Instantiate your viewController and present it with code.
I have created a view in Interface Builder with some labels and text as IBOutlets. I can view this screen perfectly when I segue to it from another view that I have defined in my Storyboard.
However, I have another XIB and an associated UIViewController that I want to access that view from. Because my XIB is not in the Storyboard, I cant segue to it. Instead I have to execute the transition programmatically.
PlantDetailViewController *plantDetailVC = [[PlantDetailViewController alloc] init];
[self.currentNavigationController pushViewController:plantDetailVC animated:YES];
When this code is executed it transitions to the view but the view is just blank. I have debugged the code and it enters viewDidLoad and viewWillAppear however all my IBOutlets are NIL....so nothing it showing up on screen!
Can anyone tell me why they might be NIL and how I can initialize them?
Thanks
Brian
It sounds like you're saying you have a PlantDetailViewController set up in your storyboard, and some OtherViewController that was created outside of your storyboard. Now you want OtherViewController to instantiate the PlantDetailViewController that was set up in your storyboard.
Let's say your storyboard is named MainStoryboard.storyboard.
First, you need to set the identifier of the PlantDetailViewController in your storyboard. You do this in the Attributes inspector, under the View Controller section. Let's say you set it to PlantDetail.
Then, in OtherViewController, this should work:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
PlantDetailViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"PlantDetail"];
[self.currentNavigationController pushViewController:vc animated:YES];
-init doesn't load a nib file for you, if you want to load a nib use -initWithNibName:bundle:
If you use nib naming conventions you can pass nil to load a nib whose name matches your class and the default bundle, i.e. [[PlantDetailViewController alloc] initWithNibName:nil bundle:nil], see the docs for -nibName for details.