Multiple storyboards not loading localization - ios

I have an application that has a few different Storyboards, and is using Base Internationalization for localizing into French. The Main.storyboard that has its .strings file with translations loads with French just fine. However, when I instantiate a new storyboard, and present it, it remains in English. I was simply doing this to load the storyboard before:
UIStoryboard *upcomingStoryboard = [UIStoryboard storyboardWithName:storyboardName bundle:nil];
/// Code to present initial view controller.
This just loads the English storyboard. I then tried following the instructions from this site, which changed my code to:
NSString *language = #"Base";
NSBundle *mainBundle = [NSBundle mainBundle];
NSString *preferred = [[mainBundle preferredLocalizations] objectAtIndex:0];
if ([[mainBundle localizations] containsObject:preferred]) {
language = preferred;
}
NSBundle *bundle = [NSBundle bundleWithPath:[mainBundle pathForResource:language
ofType:#"lproj"]];
UIStoryboard *upcomingStoryboard = [UIStoryboard storyboardWithName:storyboardName bundle:bundle];
All this did was cause the app to crash when loading the storyboard, which is probably because there no actual storyboard file in the fr.lproj, just a .strings file. Has anyone had any success with this?

I'm using multiple storyboards in my localised app. None of them are set as the "Main Interface" file. They are all loaded in code depending on where the user needs to be in the app.
Essentially I have a login storyboard that walks the user through logging in and an "app" storyboard for the content of the app.
The project uses base internationalisation (with English as the development language) and strings files for all the translations (nibs, storyboards and code).
They are loaded through a method like this...
- (void)showStoryboardWithName:(NSString *)storyboardName transition:(UIViewAnimationOptions)transition
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:storyboardName bundle:[NSBundle mainBundle]];
UIViewController *controller = [storyboard instantiateInitialViewController];
[self showViewController:controller withTransition:transition];
}
I have 15ish languages localised in the app and they all work with this.

Related

iOS - access class method using targets

I have the following code:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MyViewController" bundle:nil];
UINavigationController *navControllerInstance = [storyboard instantiateViewControllerWithIdentifier:NSStringFromClass([MyViewController class])];
When I use targets my problem is [MyViewController class] is returning "MyTarget_2.MyViewController" then my app crash because "'Storyboard (<UIStoryboard: 0x600001e65d80>) doesn't contain a view controller with identifier "
I have two targets:
MyTarget and MyTarget_2 and is only failing with the last one.
I don't understand is why [MyViewController class] is returning
MyTarget.MyViewController. When I start a new project this is not happening, only returns MyViewController . Why is such a difference?
This seems to be related because I'm using swift+objective-c
Calling NSStringFromClass on a Swift Class in Objective-C returns module mangled name
You can get class name like this :
NSString *className = [[NSStringFromClass([MyViewController class]) componentsSeparatedByString:#"."] lastObject];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MyViewController" bundle:nil];
UINavigationController *navControllerInstance = [storyboard instantiateViewControllerWithIdentifier:className];
and make sure that your storyboard id should be MyViewController
Did you give Identifier to your ViewController in storyboard ?
You can give it against Storyboard ID in ViewController's identify Inspector section.
Because ,
UINavigationController *navControllerInstance = [storyboard instantiateViewControllerWithIdentifier:NSStringFromClass([MyViewController class])];
method work on the identifier and not on class name
I think you haven't copied that particular storyboard in to your target. You can verify it. Click on target. Then on Build Phase -> Copy bundle resource. Check if storyboard file exist in both targets. And if storyboard is not there click on + button add that file. Clean and run. Hope it help.

Programmatically load ViewController from Storyboard in app with multiple storyboards

I am working on an application that is transitioning to having multiple storyboards for different sections of the app. They are linked together by programmatically loading them at the appropriate times.
In a function for when a UIButton is tapped, it should programmatically load a storyboard. The code is like so:
- (void)loginTapped:(id)sender {
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Home.storyboard" bundle:nil];
UIViewController *vc = [sb instantiateViewControllerWithIdentifier:#"homeStoryboard"];
vc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:vc animated:YES completion:NULL];
}
The storyboard is named the name listed in in the function:
and is listed as a target in the project settings appropriately:
and has the appropriate ID like so:
However, even after setting all this I get the error:
'NSInvalidArgumentException', reason: 'Could not find a storyboard named 'Home.storyboard' in bundle NSBundle
I have tried to follow the advice from this post here, but nothing has worked. How do I get this storyboard to load?
The solution (as mentioned in the comments above) is to not include the .storyboard when providing the name of the storyboard.
Old
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Home.storyboard" bundle:nil];
New
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Home" bundle:nil];
Try this:
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Home" bundle:nil];
To call any ViewController programmatically in ios using Objective c:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:Home bundle:nil];
yourDestinationViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#homeStoryboard];
[self presentViewController:vc animated:YES completed:^{}];
yourDestinationViewController in the code is your view controller.h file.
You want to import that viewcontroller.h file in your program, where you want to call the View controller programmatically.
and to create the property like below,
#import "viewcontroller.h"
#property viewController *yourDestinationViewController;

Can I change 'main storyboard file base name' in app?

I have made a pro and lite version app using different target from an project. These two apps use different storyboard and info.plist file.
I want to make in app purchase button in lite version app for operating like pro version app. For do that, I need to change the storyboard file that lite version uses to pro version's storyboard file when users buy in app purchase feature.
The storyboard file name used is stored at 'main storyboard file base name' in xxx-info.plist file. So, can I change the storyboard file base name when users do something. I don't know it's possible or not.
How can I get this?
Thank you.
You can set it dynamically at startup:
// set storyBoardName according to upgrade status
UIStoryboard *storyBoard =
[UIStoryboard storyboardWithName:storyBoardName bundle:nil];
UIViewController *initViewController =
[storyBoard instantiateInitialViewController];
[self.window setRootViewController:initViewController];
So I guess it is OK to start up the app again after upgrade.
Yes, in your AppDelegate application:didFinishLaunchingWithOptions:launchOptions method you can get the storyboard name from your plist, and then load the storyboard based on this setting. Or, you could store the storyboard name in UserDefaults instead, and update that setting after the user has paid for the pro version.
Or, you can use UserDefaults to store just whether the user has upgraded or not, and keep the storyboard names as constants in appdelegate:
#define kStoryboardLite #"LiteStoryboard.storyboard"
#define kStoryboardPro #"ProStoryboard.storyboard"
...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSString *storyboardName;
NSString *userType = [[NSUserDefaults standardUserDefaults] objectForKey:#"userType"];
if ([userType isEqualToString:#"pro"]) {
storyboardName = kStoryboardPro;
} else {
storyboardName = kStoryboardLite;
}
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:storyboardName bundle:nil];
UIViewController *initialViewController = [storyboard instantiateInitialViewController];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = initialViewController;
[self.window makeKeyAndVisible];
}
If you use this approach, you would have to ask your user to restart the app to load the other storyboard.

how to convert UIStoryBoard code to xib file code

I create one application that has side menu (like facebook) and this menu open fron left side.
I want create this app with xib file and I help from one project. in that project exist UIStoryBoard and I have problem with this code :
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
self.leftVC = (LeftVC*)[storyboard instantiateViewControllerWithIdentifier:#"LeftVC"];;
[self.navigationController.view.superview insertSubview:self.leftVC.view belowSubview:self.navigationController.view];
I want to use xib file instead storyboard. (my xib file is : LeftVC.xib)
I hop you have corresponding VC for LeftVC. Then do like
LeftVC *leftVC = [LeftVC alloc][initWithNibName:#"LeftVC" bundle:nil];
[self.navigationController.view.superview insertSubview:self.leftVC.view belowSubview:self.navigationController.view];

Switching between StoryBoards programmatically based on locale

I have two storyBoards one for LTR(Left to Right Scripts like english , german etc) and one for arabic RTL(Right to left scripts). I want to switch between these two storyboards based on the user language selected. Currently im executing this code in AppDelegate.m file :
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSString *typeN = [[NSLocale preferredLanguages] objectAtIndex:0];
//NSBundle *myBundle= [[NSBundle alloc] init];
if([typeN compare:#"ar"] == NSOrderedSame){
UIStoryboard *us = [UIStoryboard storyboardWithName:#"RtlStoryboard" bundle: nil];
FirstViewController *myStoryBoardInitialViewController = [us instantiateInitialViewController];
myStoryBoardInitialViewController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
NSLog(#"arabic- RTL");
}
else {
UIStoryboard *ms = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle: nil];
FirstViewController *myStoryBoardInitialViewControl = [ms instantiateInitialViewController];
myStoryBoardInitialViewControl.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
NSLog(#"english- ENG");
}
Is this the right way of doing it, though for arabic [typeN compare:#"ar"] if block is getting executed But it is still loading LTR storyBoard. Also the view controllers are same for both storyboards, because the code logic is same, its just the screen formatting is different. Please provide pointers or detail me on this issue.

Resources