Switching between StoryBoards programmatically based on locale - ipad

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.

Related

UISplitViewController: Does not show up when setting it up pragmatically

I am trying to setup a splitviewcontroller using storyboards. The code below is what I have so far. However, it is showing a black screen. I have a storyboard name Main. I have two viewcontrollers in the storyboard. I read how to do this from an article, but can't get it to work. I must be missing something small. Any help is appreciated.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Main"
bundle:nil];
ViewController *firstVC = [sb instantiateViewControllerWithIdentifier:#"ViewController"];
ViewController1 *secondVC = [sb instantiateViewControllerWithIdentifier:#"ViewController1"];
CGRect frameFirstVC = firstVC.view.frame;
frameFirstVC.size.width = 100;
CGRect frameSecondVC = secondVC.view.frame;
frameSecondVC.size.width = 100;
UISplitViewController* splitVC = [[UISplitViewController alloc] init];
splitVC.viewControllers = [NSArray arrayWithObjects:firstVC, secondVC, nil];
[self.window addSubview:splitVC.view];
[self.window makeKeyAndVisible];
return YES; }
You shouldn't add the split view controller's view as a subview of your window directly. Instead, set the window's rootViewController property:
self.window.rootViewController = splitVC;
In addition to configuring the view hierarchy, this sets up additional state and layout information for the app to properly display and use the split view controller.
(I should point out that instead of writing any of this code, you could put the split view controller in your storyboard, mark it the initial view controller, then use that storyboard as your app's main interface file. That's a bit of a bigger change, though.)

Use 2 different Storyboards, one for LTR and one for RTL (NOT AUTO LAYOUT)

My app now support RTL languages, i want to add support for LTR languages.
i created additional storyboard file and set the alignment(of all the labels, buttons, pics etc..) to support LTR.
Now, how can i know that the user using LTR language and how should i tell the app to use the LTR storyboard?
i tried to use auto layout - without success.
so i decided to do it that way, any ideas?
You can try this in your app delegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
UIStoryboard *storyboard;
// Determine the text direction and load the Storyboard accordingly
if ([UIApplication sharedApplication].userInterfaceLayoutDirection == UIUserInterfaceLayoutDirectionRightToLeft) {
storyboard = [UIStoryboard storyboardWithName:#"RTL" bundle:nil];
} else {
storyboard = [UIStoryboard storyboardWithName:#"LTR" bundle:nil];
}
// Get the initial view controller
UIViewController *viewController = [storyboard instantiateViewControllerWithIdentifier:#"InitialViewController"];
self.window.rootViewController = viewController;
[self.window makeKeyAndVisible];
return YES;
}

How can I load a view "properly" iOS

My app consists of a navigation controller and view controllers. Some parts of my UI is done on storyboard and some are initiated from code (in viewDidLoad). My goal is to load childViewController X (consists of a back button, nag bar, label and table) when the app is launched from a push notification "properly" through this method in appDelegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
This might be a simple question to you guys but I've asked several questions the pass few days (you can look at my questions history). After trying several methods, my app either:
crashes
loads without navigation bar
loads with navigation bar but no label (back button does not work)
loads with navigation bar but with black screen underneath
Only the tableView is dragged onto storyboard. The navigation bar is inferred but I have code that dictates its back button and title. The rest is all done through code in the .m file.
I know people have asked this question before but none of the methods worked. How can I load this childViewController properly through a push notification?
EDIT/UPDATE:
My code so far:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSDictionary *dictionary = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (dictionary != nil)
{
UIStoryboard *mainstoryboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
UIViewController* firstVC = [mainstoryboard instantiateViewControllerWithIdentifier:#"NotificationsViewController"];
[self.window.rootViewController addChildViewController:firstVC];
[(UINavigationController *)self.window.rootViewController pushViewController:firstVC animated:NO];
self.window.rootViewController.childViewControllers);
}}
Error Code:
'-[SWRevealViewController pushViewController:animated:]: unrecognized selector sent to instance 0x14575f20'
SWRevealViewController is my library for my sidebar menu view controller.
UPDATE2:
I've also tried this method:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
UIViewController *initViewController = [storyboard instantiateViewControllerWithIdentifier:#"NotificationsViewController"];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = initViewController;
[self.window makeKeyAndVisible];
This loads the correct viewController but without a navigation bar.
Try this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSDictionary *dictionary = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if(dictionary != nil) {
UIStoryboard *mainstoryboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
UIViewController *firstVC = [mainstoryboard instantiateViewControllerWithIdentifier:#"NotificationsViewController"];
UINavigationController *navigationController = (UINavigationController *)self.window.rootViewController;
// Navigation already created
if(navigationController) {
[navigationController pushViewController:firstVC animated:NO];
// Navigation not created
} else {
UINavigationViewController *navigationController = [[UINavigationViewController alloc] initWithRootController:firstVC];
[self.window setRootViewController:firstVC];
[self.window makeKeyAndVisible];
}
}
return YES;
}
You had some problem in your code:
You need to have a UINavigationController in order to have a navigation bar and manage the push/pop actions, so your window root controller should be a UINavigationController.
If you need to initialize a UINavigationController the best and simple way is to initialize it with a root controller directly, so leave the push/pop for user actions: an application has always a root controller, so why don't you create it immediately?
The "addChildController" is another thing: it is used to create custom container controller, it means that you have to implement all the business logic manually. I suggest you to use it only if you are experienced enough, since it could be difficult - Cocoa has enough components to leave it for a small set of applications.
You are using a third part controller, the "SWRevealViewController". They should have an example project, you can try to "copy" it and them customize it for your own purpose.
Let me know if your code works well, otherwise post the new error and I'll try to help you

UISplitView with Multiple Detail Views (with Storyboard)

I've been trying to create a version of this code using a storyboard:
I want to be able to switch between two different detail views, depending on the cell selected in the navigation table. I've tried to implement this by creating a SplitViewManager with a custom setter method that swaps out the detail views each time a different cell is selected. This is the same approach that Apple's sample code uses. The SplitViewManager follows the delegate.
I think my issue is that I haven't connected my splitViewController.delegate to anything, so I can't assign the splitViewManager to anything either. But I can't figure out what I would even connect the delegate to in the storyboard. Please let me know if I'm being an idiot here (almost definitely). Thanks!
My code is below:
DFMAppDelegate.m:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.splitViewController = (UISplitViewController *)self.window.rootViewController;
self.splitViewManager = (DFMSplitViewManager *)self.splitViewController.delegate;
NSLog(#"split view controller: %#", self.splitViewController); // not null
NSLog(#"split view controller delegate: %#", self.splitViewController.delegate); // is null
NSLog(#"split view manager: %#", self.splitViewManager); // is null.
// But i'm not sure how to assign splitViewController.delegate or splitViewManager in the storyboard.
return YES;
}
DFMSplitViewManager.m:
- (void)setDetailViewController:(UIViewController<SubstitutableDetailViewController> *)detailViewController
{
self.detailViewController = detailViewController;
// Update the split view controller's view controllers array.
// This causes the new detail view controller to be displayed.
UIViewController *navigationViewController = [self.splitViewController.viewControllers objectAtIndex:0];
NSArray *viewControllers = [[NSArray alloc] initWithObjects:navigationViewController, self.detailViewController, nil];
self.splitViewController.viewControllers = viewControllers;
}
DFMMasterViewController.m:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
DFMAppDelegate *appDelegate = (DFMAppDelegate *)[[UIApplication sharedApplication] delegate];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
if (indexPath.row == 0) {
NSLog(#"clicked cell 1");
DFMDetailViewController *detailViewController = [storyboard instantiateViewControllerWithIdentifier:#"ViewController"];
[appDelegate.splitViewManager setDetailViewController:detailViewController];
}
else {
NSLog(#"clicked cell 2");
DFMDetailCollectionViewController *detailCollectionViewController = [storyboard instantiateViewControllerWithIdentifier:#"CollectionViewController"];
[appDelegate.splitViewManager setDetailViewController:detailCollectionViewController];
}
}
Turns out you can use the interface builder to add NSObjects to View Controllers. Once I did that, I changed the NSObject's class to DFMSplitViewManager, set it as the SplitViewController's delegate, and it was pretty straight forward from there.
I am facing exactly the same problem as yours. Don't know wether you find out the solution or not, here is the solution I found.
Use following code in your AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController;
self.detailViewManager = [[DetailViewManager alloc] init];
self.detailViewManager.splitViewController = splitViewController;
self.detailViewManager.detailViewController = splitViewController.viewControllers.lastObject;
splitViewController.delegate = self.detailViewManager;
if ([splitViewController respondsToSelector:#selector(setPresentsWithGesture:)])
[splitViewController setPresentsWithGesture:YES];
return YES;
}
The rest of code is the same as what Apple has provided.
Basically, self.detailViewManager is our split view controller, when you select cell in table, self.detailViewManager will reset the detail view (if I'm not wrong). I'm new to Xcode, so anyone please correct me if I'm wrong.
Here is the solution link, answered by hallmark.

get active storyboard

I'm using the code bellow to check if the user is logged in or logged out, and it's working fine. But because I'm getting the storyboard by name, I'm always sending the user to the iPhone "in" or "out" view controller. It's gonna work if I get the active storyboard. How can I fix the code?
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
BOOL user = ...;
NSString *segue = user ? #"in" : #"out";
UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:#"iPhone" bundle:nil];
UIViewController *viewController = [storyBoard instantiateViewControllerWithIdentifier:segue];
[self.window setRootViewController:viewController];
return YES;
}
If all you're looking to do is to get the viewController from a different storyboard depending on whether your app is running on an iPad vs. an iPhone, you could do this with an if statement:
NSString *storyboardName;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
storyboardName = #"iPad";
} else {
storyboardName = #"iPhone";
}
UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:storyboardName bundle:nil];
If you really need to get the "active" storyboard no matter the situation, this prior answer may help you:
UIStoryboard: What's the Correct Way to Get the Active Storyboard?

Resources