iOS: Tab change programmatically - storyboard - ios

I am trying to change tab programmatically in storyboard but getting error
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
TabViewController *tabBarCon = [storyboard
instantiateViewControllerWithIdentifier:#"tabBar"];
tabBarCon.selectedViewController = [tabBarCon.viewControllers objectAtIndex:1];
Error
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil'
Here tabBarCon.viewControllers is not empty.
NSLog(#"%#",tabBarCon.viewControllers); giving
(
"<FirstViewController: 0x16642020>",
"<SecondViewController: 0x173c4c00>",
"<ThirdViewController: 0x166db570>",
"<ForthViewController: 0x166d17c0>",
"<FifthViewController: 0x166066a0>"
)

You need to have instance of tabbarcontroller.
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
TabViewController *tabBarCon = [storyboard instantiateViewControllerWithIdentifier:#"tabBar"];
This statement creates new instance of tabbar from storyboard.
[self.tabBarController setSelectedIndex:1];
If you are within the tab bar controller then you will easily get the instance using self.tabBarController

Try This:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
TabViewController *tabBarCon = [storyboard instantiateViewControllerWithIdentifier:#"tabBar"];
[self.tabBarController setSelectedIndex:1];

Try This
UITabBarController *controller =(UITabBarController *)
self.window.rootViewController;
[controller setSelectedIndex:1];
i have tried on Appdelegate it is working

Related

Initialize Swift storyboard from Objective-C

I'm trying to add a new storyboard in Swift to an old Objective-C app:
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"MainStoryboard01" bundle:nil];
UIViewController *vc = [sb instantiateViewControllerWithIdentifier:#"OnboardingViewController"];
[self presentViewController:vc animated:YES completion:NULL];
With Swift storyboard:
I'm always getting error:
'Could not find a storyboard named 'MainStoryboard01' in bundle NSBundle <.../Developer/CoreSimulator/Devices/753636C1-ABB5-4D6E-B184-5C4638FB2CE9/data/Containers/Bundle/Application/398410C0-BB2C-4574-B058-95D30F8D1B5D/Credit Call.app> (loaded)'
Calling swift classes like
TestClass *instance = [TestClass new];
[instance testFunction];
Normally works. Any idea how to call swift storyboard + it's swfit controller in Objective-C app?
// EDIT:
I finally get working this:
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Onboarding" bundle:nil];
UIViewController *vc = [sb instantiateViewControllerWithIdentifier:#"MainStoryboard01"];
but on next line
[self presentViewController:vc animated:YES completion:NULL];
I get this error:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[MyAppDelegate presentViewController:animated:completion:]: unrecognized selector sent to instance 0x6080000b3b60'
Any ideas? I need to replace this with the storyboard:
Registration *reg = [[Registration alloc] init];
registrationNav = [[UINavigationController alloc] initWithRootViewController:reg];
[reg release];
[self.mainBackgroundView addSubview:[registrationNav view]];
=> https://codepaste.net/jkfras I've added skeleton of the MyAppDelegate.m
You are making mistake here, MainStoryboard01 that you have set is Storyboard Identifer using that you can called instantiateViewControllerWithIdentifier. It is not the another storyboard name. So its should be simply like this.
//You need to put storyboard name here the check the image for more detail
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *vc = [sb instantiateViewControllerWithIdentifier:#"MainStoryboard01"];
[self presentViewController:vc animated:YES completion:nil];
Edit: Try this way.
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *vc = [sb instantiateViewControllerWithIdentifier:#"MainStoryboard01"];
[self.mainBackgroundView addSubview:[vc view]];
If you want to reference to a storyboard then you should use its name, so if your storyboard has a name "MyNewStoryboard" (MyNewStoryboard.storyboard) then the right way to create its reference is like this:
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"MyNewStoryboard" bundle:nil];
Don't use a storyboard ID here. Storyboard ID you just set in the controller's attributes is the identifier for your controller. So you can use it this way:
UIViewController *vc = [sb instantiateViewControllerWithIdentifier:#"MainStoryboard01"];
Change your new controller's Storyboard ID to something more informative, so for example "OnboardingViewController", and then after putting your storyboard file name in your first line your code should be fine.

Could not load NIB in bundle: 'NSBundle ยทยทยท with name 'chosenCountry''

I want touch the UIBarButtonItem in the top right, and push a new viewController. So, the code is:
UIBarButtonItem *addButton = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemAdd
target:self
action:#selector(insertNewObject)];
self.navigationItem.rightBarButtonItem = addButton;
and method insertNewObject is:
-(void)insertNewObject{
chosenViewController *chosenCountry = [[chosenViewController alloc]initWithNibName:#"chosenCountry" bundle:nil];
//self.chosenViewController = chosenCountry;
[self.navigationController pushViewController:chosenCountry animated:YES];
}
but XCode have a error when I run 'Could not load NIB in bundle: 'NSBundle ...(loaded)' with name 'chosenCountry''
How can I fix it?
Thanks!
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
UIViewController *vc = [sb instantiateViewControllerWithIdentifier:#"chosenCountry"];
[self.navigationController pushViewController:vc animated:YES];
Since you have added your vc in storyboard, hence initWithNibName will not work.
Either use segue or use storyboard's method instantiateViewControllerWithIdentifier to instantiate the view controller
Use this code it works for you
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
yourViewController *vc = [mainStoryboard instantiateViewControllerWithIdentifier:#"chosenCountry"];
[self.navigationController pushViewController:vc animated:YES];

How to get viewcontroller in storyboard by identifier?

I try to get a viewcontroller from storyboard like this:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
ViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"vc"];
ViewController *avc = ((UINavigationController *)(_window.rootViewController)).topViewController;
But they are not the same object:
(lldb) po vc <ViewController: 0x17eaee50>
(lldb) po avc <ViewController: 0x17e72970>
Why?
They are of the same class, but different instances. instantiateViewControllerWithIdentifier instantiates a new view controller, as the name implies :).

Navigating from Appdelegate when push message received

Currently this is how my method loooks
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
NSString *screenNo =[userInfo objectForKey:#"screen"];
}
Based on the screenNo I would like to navigate to different view controllers. But I couldn't do as most of the answers given below.
Reason is that my root view is not navigation control, so I couldn't segue. It crashes the app.
when push message arrives didReceiveRemoteNotification is called and I could see the content of the message too. But it doesn't get navigated using the methods shown here.
[self.window makeKeyAndVisible];
UIStoryboard *mainStoryBoard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *vc = [mainStoryBoard instantiateViewControllerWithIdentifier:#"galleryViewController2"];
[(UINavigationController *)self.window.rootViewController pushViewController:vc animated:YES];
this is the exception
2014-07-21 18:06:53.709 Proitzen Rest[993:60b] -[RESTSecondViewController pushViewController:animated:]: unrecognized selector sent to instance 0x14e26270
2014-07-21 18:06:53.712 Proitzen Rest[993:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[RESTSecondViewController pushViewController:animated:]: unrecognized selector sent to instance 0x14e26270'
*** First throw call stack:
(0x2f480fd3 0x3a021ccf 0x2f484967 0x2f483253 0x2f3d27b8 0xff93b 0x31eb3b29 0x31eb37fb 0x31dbb05f 0x31e6d377 0x31d1c6f5 0x31c9555b 0x2f44c2a5 0x2f449c49 0x2f449f8b 0x2f3b4f0f 0x2f3b4cf3 0x342da663 0x31d0016d 0x157e69 0x3a52eab7)
libc++abi.dylib: terminating with uncaught exception of type NSException
Thanks for your time in advance.
Did you try something like this?
UIStoryboard *mainStoryBoard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *vc = [mainStoryBoard instantiateViewControllerWithIdentifier:#"galleryViewController2"];
self.window.rootViewController = vc;
Instead of pushing your new controller (it crashes because to push you need a navigation controller) you can replace current controller with the new one.
Please, take in account that you can not pop to the original controller (if you need to get back, you need a navigation)
You're trying to push a UIViewController with a UIViewController. This is not possible. You must have a UINavigationController in your app hierarchy.
You can also just set the rootViewController:
[self.window setRootViewController: newViewController];
make sure you call this method before trying to present any view controller.
[self.window makeKeyAndVisible];
You can't navigate using push and Pop from APPDelegate if you need to navigate from appDelegate to a file, Segues won't help either then You would need to load it first in your window and then make it Visible such as..
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
NSString *screenNo =[userInfo objectForKey:#"screen"];
UINavigationController *navController = (UINavigationController *)self.window.rootViewController;
firstViewController *menu = [navController.storyboard instantiateViewControllerWithIdentifier:#"firstVC"];
// First item in array is bottom of stack, last item is top.
navController.viewControllers = [NSArray arrayWithObjects:menu, nil];
[self.window makeKeyAndVisible];
}
This is what finally saved me. placed it inside didReceiveRemoteNotification method.
NSLog(#"User wanna navigate");
[self.window makeKeyAndVisible];
UIStoryboard *mainStoryBoard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *vc = [mainStoryBoard instantiateViewControllerWithIdentifier:#"moreTableViewController"];
self.window.rootViewController = vc;
UINavigationController *navController = (UINavigationController *)self.window.rootViewController;
UIViewController *evc = [mainStoryBoard instantiateViewControllerWithIdentifier:#"eventsViewController"];
[navController.visibleViewController.navigationController pushViewController:evc animated:YES];

Parent and child view in Container V

I have a project in iOS and I am trying to modify the same to use in another project. The project is working fine but when I try and Embed the Side View Controller in a tab bar controller it is giving an error
**MFSideMenuDemoStoryboard[23760:c07] -[UITabBarController setLeftMenuViewController:]: unrecognized selector sent to instance 0x757a590
2013-06-13 10:08:51.062 MFSideMenuDemoStoryboard[23760:c07] **** * * **Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UITabBarController setLeftMenuViewController:]: unrecognized selector sent to instance 0x757a590'**
i understand that there is something wrong in the Code in appDelegate .m but can't figure out
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:[NSBundle mainBundle]];
MFSideMenuContainerViewController *container = (MFSideMenuContainerViewController *)self.window.rootViewController;
UINavigationController *navigationController = [storyboard instantiateViewControllerWithIdentifier:#"navigationController"];
UIViewController *leftSideMenuViewController = [storyboard instantiateViewControllerWithIdentifier:#"leftSideMenuViewController"];
UIViewController *rightSideMenuViewController = [storyboard instantiateViewControllerWithIdentifier:#"rightSideMenuViewController"];
[container setLeftMenuViewController:leftSideMenuViewController];
[container setRightMenuViewController:rightSideMenuViewController];
[container setCenterViewController:navigationController];
return YES;
}
This is my storyboard
Your root view controller is not a MFSideMenuContainerViewController. It is a UITabBarController. If you want to use MFSideMenuContainerViewController you will want to check out the documentation: https://github.com/mikefrederick/MFSideMenu/
Here is a basic example:
UIViewController *leftSideMenuViewController = [storyboard instantiateViewControllerWithIdentifier:#"leftSideMenuViewController"];
UIViewController *rightSideMenuViewController = [storyboard instantiateViewControllerWithIdentifier:#"rightSideMenuViewController"];
MFSideMenuContainerViewController *container = [MFSideMenuContainerViewController
containerWithCenterViewController: self.window.rootViewController
leftMenuViewController: leftSideMenuViewController
rightMenuViewController: rightSideMenuViewController];
self.window.rootViewController = container;
[self.window makeKeyAndVisible];
This will replace your existing root view controller with a MFSideMenuContainerViewController and place your old root view controller as the center view controller.
As you can see in the storyboard and in the exception, your root view controller is a tab bar controller, not a side menu controller.
UITabBarController has a property viewControllers which gives you access to the controllers inside the tabBarController. You want to get the controller at index 0. This means the viewController at the first tab.
Something like this should work:
UITabBarController *tabBarController = (UITabBarController *)self.window.rootViewController;
MFSideMenuContainerViewController *container = tabBarController.viewControllers[0];
// check that container is actually a container and not something else
NSParameterAssert([container isKindOfClass:[MFSideMenuContainerViewController class]]);

Resources