Switching between storyboard localization - ios

I have application using storyboard with two language (Ar/En) how i can switch from Arabic storyboard to English storyboard without need to change language iPhone settings (At run time).
When user change manually the language, i use :
+ (void)setDefaultLocalizationLanguage:(NSString *)language{
[UserPreferences setDefaultLanguage:language];
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:language, nil] forKey:#"AppleLanguages"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
In AppDelegate, I add method switchTolanguage:
-(void)switchTolanguage:(NSString *)lang{
NSBundle *bnd = [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:lang ofType:#"lproj" ]];
UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:#"Main" bundle:bnd];
UIViewController *initViewController = [storyBoard instantiateInitialViewController];
self.window.rootViewController = initViewController;
}
I execute the last method in my ViewController :
AppDelegate *appdelagate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
[appdelagate switchTolanguage:[UserPreferences defaultLanguage]];
But I have the same storyboard localization with this logs:
Could not load the "4_icon_4.png" image referenced from a nib in the bundle with identifier "(null)"
Could not load the "1_logo.png" image referenced from a nib in the bundle with identifier "(null)"
Could not load the "1_bacground_img.png" image referenced from a nib in the bundle with identifier "(null)"
But when I kill application and I open it, I have the good storyboard.

Related

Relaunch app after changing the language in Objective-C

I am changing the language using
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:#"fr", #"en", nil] forKey:#"AppleLanguages"];
[[NSUserDefaults standardUserDefaults] synchronize];
when user taps on a button.But the user must restart the app in order for language to change.
Is there anyway possible to restart or relaunch the app when user taps the button?
Yes. There is a possibility, you can do it as Instagram iOS app. In that after changing the language in setting, they will show an alert to restart. When pressed they will force quit the app.
Note: Please check with apple guidelines before implementing it.
You can go to the main storyboard after changing the language.
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *vc = [storyboard instantiateInitialViewController];
[UIApplication sharedApplication].delegate.window.rootViewController = vc;

UIViewController did not deallocate itself

I'm working on an app that changes it's rootViewController depending on it's state. To make a switch I use this code:
- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[self createManagedDocumentAndContext];
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
NSString *storyboardId = [userDefaults boolForKey:#"Profile Created"] ? #"User Stats" : #"Profile";
self.window.rootViewController = [self.window.rootViewController.storyboard instantiateViewControllerWithIdentifier:storyboardId];
return YES;
}
To switch back I call this method from presented ProfileVC:
- (void)returnOldRootViewController
{
UIWindow *currentWindow = [UIApplication sharedApplication].keyWindow;
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
OLDUserStatsVC *userStatsVC = [storyboard instantiateViewControllerWithIdentifier:#"User Stats"];
userStatsVC.userProfile = self.userProfile;
[currentWindow setRootViewController:userStatsVC];
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setBool:YES forKey:#"Profile Created"];
}
THE PROBLEM: rootViewController is changed, but previous one is not deallocated. It stays on the "background" of the app - I can see it when VC changes to another one.
The question is how to release it properly?
Thank you very much!
The real problem here is that you are changing the root view controller of the window. Don't do that. You should be setting this once and never again. There should be just one root view controller for the lifetime of the app.
Find another architecture for displaying the correct view controller and switching between them as desired. For example, they might both be children of the root view controller, or one might be a presented view controller in front of the other.

Multiple storyboards not loading localization

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.

Create multiple storyboard iPhone/ipad

Create multiple storyboard iPhone/ipad,use the same viewcontroller,but iPhone storyboad can run,iPad error message(can run on ios simulator,but can't not run on my ipadair).
this is my code:
NSBundle *resource = [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:#"LibraryResource" ofType:#"bundle"]];
[resource load];
UIUserInterfaceIdiom userIdiom = [[UIDevice currentDevice] userInterfaceIdiom];
if (userIdiom == UIUserInterfaceIdiomPad) {
UIStoryboard* mainStoryboard = [UIStoryboard storyboardWithName:#"Main_iPad" bundle:resource];
LibraryController* LibraryController = [mainStoryboard instantiateViewControllerWithIdentifier:#"LibraryController"];
[self presentViewController:LibraryController animated:YES completion:nil];
} else if (userIdiom == UIUserInterfaceIdiomPhone) {
UIStoryboard* mainStoryboard = [UIStoryboard storyboardWithName:#"Main_iPhone" bundle:resource];
LibraryController* LibraryController = [mainStoryboard instantiateViewControllerWithIdentifier:#"LibraryController"];
[self presentViewController:LibraryController animated:YES completion:nil];
}
error message:
2014-03-04 14:24:25.515 AddLibrary[311:60b] Cannot find executable for CFBundle/CFPlugIn 0x157e0aad0 </var/mobile/Applications/184A78F9-1488-4C34-AD5C-10170067ACEA/AddLibrary.app/Library9898API Resource.bundle> (not loaded)
2014-03-04 14:24:25.522 AddLibrary[311:60b] Unknown class LibraryController in Interface Builder file.
Make sure you have included your file to your target that is your app bundle. Ensure you have checked the target membership.
add your view controller to your build phases.
Clean and rebuild it again. It should work.
If not then reset the simulator then try
Rename your view controller files and class name and then add it your project.
iPadAir must support (64-bit),use the old project not change

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.

Resources