I have four apps and want to combine them into one app.
If I added those projects into a project workspace -- for example there's project A and project B --
is it possible to click a button and go to project A's root controller,
then click another button go to project B's root controller ?
If it's possible, how can I do that?
is it possible to click a button and go to project A's root
controller, then click another button go to project B's root
controller?
A natural way to do that would be to manage the various "root" view controllers with a tab bar controller. For example, your app delegate could create a UITabBarController programmatically, and then load it with the root view controllers from each of your storyboards. It'd go something like this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.tabBarController = [[UITabBarController alloc] init];
// Project 1
UIStoryboard *storyboard1 = [UIStoryboard storyboardWithName:#"Project1" bundle:nil];
UIViewController *controller1 = [storyboard1 instantiateInitialViewController];
// Project 2
UIStoryboard *storyboard2 = [UIStoryboard storyboardWithName:#"Project2" bundle:nil];
UIViewController *controller2 = [storyboard1 instantiateInitialViewController];
// Project 3
UIStoryboard *storyboard3 = [UIStoryboard storyboardWithName:#"Project3" bundle:nil];
UIViewController *controller3 = [storyboard1 instantiateInitialViewController];
// Project 4
UIStoryboard *storyboard4 = [UIStoryboard storyboardWithName:#"Project4" bundle:nil];
UIViewController *controller4 = [storyboard1 instantiateInitialViewController];
// Add the controllers to the tab controller
[self.tabBarController setViewControllers:#[controller1, controller2, controller3, controller4]
animated:NO];
//...put any other app initialization stuff here...
return YES;
}
At this point the tab bar will have four buttons, one for each "root" view controller, and you'll be able to switch between them at will.
I haven't compiled the above, but it should be enough to get you started. You will of course have to sort out any dependancies that the various view controllers might have on the app delegate, etc. But that shouldn't be too difficult. You should also make sure that each view controller is configured with a tab bar item, so that the tab bar controller will know what icon and name to use on the corresponding button.
Related
To display mini view with controls for chromecasting video in app , root view need to be changed progrmatically. the below code need to be added to the storyboard.
// Wrap main view in the GCKUICastContainerViewController and display the mini controller.
UIStoryboard *appStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UINavigationController *navigationController =
[appStoryboard instantiateViewControllerWithIdentifier:#"MainNavigation"];
GCKUICastContainerViewController *castContainerVC =
[[GCKCastContext sharedInstance] createCastContainerControllerForViewController:navigationController];
castContainerVC.miniMediaControlsItemEnabled = YES;
self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
self.window.rootViewController = castContainerVC;
But i made tabbar controller app , rootview intiated from storyboard. can somebody help me to change or modify the rootview to get miniView (container view) in tabbar application?
Changing root view when using tab view does not look mandatory thing to me just try adding the complete navigationController object itself on the tab.
By this way on any one of the tab is will have your mini view with controls.
I am making a messaging app on ios that will have multiple folders for different types of messages. I will be using a navigation controller structure and would like the root view to be where the user can choose which folder to view. However, when I first segue to the navigation controller I would like the inbox folder view to display directly (ie. bypass the root view). Apples mail app has a similar structure (launches inbox when it opens). how can I do this?
It really depends on how the relationship is between the first view controller and the second view controller. If you want to do something like this, why don't you put your second view controller as the root controller of the UINavigationController.
Anyway, if you still want to do it the way you describe, you can just direct to the second view controller using the viewDidLoad method from your root view controller. But, it will make the UI looks clumsy.
try to use this code :
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
UIStoryboard *board = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
ViewController *controller1 = [board instantiateViewControllerWithIdentifier:#"firstView"];
UINavigationController *navController = [[UINavigationController alloc]initWithRootViewController:controller1];
SecondViewController *secondView = [board instantiateViewControllerWithIdentifier:#"secondView"];
[controller1 addChildViewController:secondView];
[self.window setRootViewController:navController];
return YES;
}
Hope this will help you.
Write this code in didFinishLaunchingWithOptions of AppDelegate.m
UIStoryboard *MainStoryboard = [UIStoryboard storyboardWithName:#"Main"
bundle: nil];
UINavigationController *controller = (UINavigationController*)[MainStoryboard
instantiateViewControllerWithIdentifier: #"YourStoryBoardID"];
NeededViewController *need=[MainStoryboard instantiateViewControllerWithIdentifier:#"YourStoryboardID"];
[controller setViewControllers:[NSArray arrayWithObject:need] animated:YES];
self.window.rootViewController=controller;
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?
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.
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.
It looks like you have your rootViewController set to a custom controller of type SWRevealViewController. If you want to call pushViewController:animated: on rootViewController, it must be a UINavigation controller. Currently you are calling it on a controller that does not respond to that message.
In your Storyboard make sure you drag a UINavigationController onto the canvas and move the root-view-controller arrow in InterfaceBuilder to point to it. Then load whatever ViewController you want into the navigationController. (i.e. your code at the top of your question should work).
I am creating a turn based game and would like to know the correct process for my workflow. At present I have the following:
Home View Controller (which has a UITableView)
Click on row from section 1 > Loads a UINavigationController with path 1
Click on row from section 2 > Loads a UINavigationController with path 2
As an example:
path 1 - play your turn
path 2 - guess your turn
Each path has around 4-5 UIViewControllers loaded into the navigation controller.
Now I am at the stage where once path 2 is complete the user should then play their turn too (ie take path 2 then path 1).
What is the correct way to complete this? should I create a segue from the last controller in path 2 > leading to path 1. The issue is that path 2 has a UIViewController that has a UIImageView with a large image in and it would hang around in memory. Ideally it is cleared as such, before the user starts path 1 (after path 2 is complete)
I have tried popToRootViewControllerAnimated but its not working when we want movetopath2.
We can store some checkpoints in NSUserDefaults and then segue accordingly but that approach doesn't work in this case.
[self.navigationController popToRootViewControllerAnimated:YES];
Finally I have found solution as follows:
Start with below working code and change it as per your app logic
ViewController.m File
#pragma mark - UITableViewDelegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
if (indexPath.section == 0)
{
UIStoryboard *mainStoryBoard = [UIStoryboard storyboardWithName:#"Main" bundle:[NSBundle mainBundle]];
PathOneViewController *pathController = [mainStoryBoard instantiateViewControllerWithIdentifier:#"PathOneViewController"];
[self.navigationController pushViewController:pathController animated:YES];
}
else
{
UIStoryboard *mainStoryBoard = [UIStoryboard storyboardWithName:#"Main" bundle:[NSBundle mainBundle]];
PathTwoViewController *pathController = [mainStoryBoard instantiateViewControllerWithIdentifier:#"PathTwoViewController"];
[self.navigationController pushViewController:pathController animated:YES];
}
}
PathOneDetailViewController.m File
- (IBAction)actionMoveToPathTwo:(id)sender { // Move to path two
AppDelegate *appDelegateTemp = [[UIApplication sharedApplication]delegate];
UIViewController* rootController = [[UIStoryboard storyboardWithName:#"Main" bundle:[NSBundle mainBundle]] instantiateViewControllerWithIdentifier:#"PathTwoViewController"];
UINavigationController* navigation = [[UINavigationController alloc] initWithRootViewController:rootController];
appDelegateTemp.window.rootViewController = navigation;
}
- (IBAction)actionMoveToHome:(id)sender { // Move to table View
AppDelegate *appDelegateTemp = [[UIApplication sharedApplication]delegate];
UIViewController* rootController = [[UIStoryboard storyboardWithName:#"Main" bundle:[NSBundle mainBundle]] instantiateViewControllerWithIdentifier:#"ViewController"];
UINavigationController* navigation = [[UINavigationController alloc] initWithRootViewController:rootController];
appDelegateTemp.window.rootViewController = navigation;
}
PathTwoDetailViewController.m File
- (IBAction)actionMoveToHome:(id)sender { // Move to table View
AppDelegate *appDelegateTemp = [[UIApplication sharedApplication]delegate];
UIViewController* rootController = [[UIStoryboard storyboardWithName:#"Main" bundle:[NSBundle mainBundle]] instantiateViewControllerWithIdentifier:#"ViewController"];
UINavigationController* navigation = [[UINavigationController alloc] initWithRootViewController:rootController];
appDelegateTemp.window.rootViewController = navigation;
}
- (IBAction)actionMoveToPath1:(id)sender { // Move to path one
AppDelegate *appDelegateTemp = [[UIApplication sharedApplication]delegate];
UIViewController* rootController = [[UIStoryboard storyboardWithName:#"Main" bundle:[NSBundle mainBundle]] instantiateViewControllerWithIdentifier:#"PathOneViewController"];
UINavigationController* navigation = [[UINavigationController alloc] initWithRootViewController:rootController];
appDelegateTemp.window.rootViewController = navigation;
}
Fire a notification from path 2
Be sure you subscribe to that notification in Home View Controller
In the notification handler method in Home View Controller, call the
current navigation controller's popToRootViewControllerAnimated:.
Manually call the segue to start path 1.
The answer that worked for me was actually a much more simple approach. Adding a ViewController reference to the starting view controller for Path2. Then simply changing the view controllers in the UINavigationController stack. As the navigation controller is not subclassed or doesn't need to be this works fine.
- (IBAction)completeButtonPressed:(id)sender {
NSLog(#"complete button pressed");
Path2ViewController *path2StartVC = [[UIStoryboard storyboardWithName:#"Main" bundle:[NSBundle mainBundle]] instantiateViewControllerWithIdentifier:#"Path21VC"];
[self.navigationController setViewControllers:[NSArray arrayWithObject:path2StartVC] animated:YES];
}
I will drop a sample project onto github for reference shortly.
I would suggest you set your first controller as a UINavigationController and set its root control to the "Home View Controller" (UITableView). I'll call this the root navigation controller for now on. You then can keep the rest of the app's structure the same as you have it now, with one UINavigation controller for each route.
This would give you the advantage of being able to call the root navigation controller popToRootViewControllerAnimated:. Which in this case would be your "Home View Controller". There is one slight disadvantage to this and that is with your paths you can't just call popToRootViewControllerAnimated: on the current navigation controller when on a path. Since this would return you to the beginning of the path that you are on.
But this is easily fixed by keeping a reference to the root navigation controller. Which I would do by subclassing UINavigationController and just adding a property that stores a reference to the root view controller. The assignment would need to be done while the view controllers are transitioning from the table view to the navigation controllers that control one of your two paths. I think prepareForSegue:sender: would be your best bet to handle this.
As for your worry of the UIImageView staying in memory. You do not need to worry about it. When the view controller unloads it will unload the UIImageView as well. The only way you could keep a view controller from unloading is keeping a strong reference to it in another view controller. Which sometimes you want eg. parent / child relationship sometimes you don't eg. segue between view controllers. But passing properties between view controllers should be fine. For more info check out View Controller Guide
There are potentially a ton of different ways to solve this question. So, I would take my answer as a starting point and adapt it to what works best for the future of your app and your code style.
I'm implememting a design based on the TabbedBanner example in the iAdSuite. I have a UINavigationController in the first tab. In that UINavigationController I have a view controller that simply has a button that pushes to another view controller. The pushed view controller is set to Hide Bottom Bar On Push in Interface Builder.
Here is the code where I'm setting up the UITabBarController.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:[[NSBundle mainBundle].infoDictionary objectForKey:#"UIMainStoryboardFile"] bundle:[NSBundle mainBundle]];
_tabBarController = [storyboard instantiateViewControllerWithIdentifier:#"TabBarController"];
_tabBarController.delegate = self;
FirstViewController *firstView = [storyboard instantiateViewControllerWithIdentifier:#"FirstViewController"];
UINavigationController *firstNav = [[UINavigationController alloc] initWithRootViewController:firstView];
_tabBarController.viewControllers = #[[[BannerViewController alloc] initWithContentViewController:firstNav], ];
self.window.rootViewController = _tabBarController;
[self.window makeKeyAndVisible];
return YES;
}
Everything works except the TabBar does not get hidden when I push to the next view controller. I have tried hiding the TabBar using the Interface Builder check box as well as using nextViewController.hidesBottomBarWhenPushed = YES and neither way works.
If I remove the BannerViewController implementation, the TabBar hides exactly as it should.
It seems to me that the BannerViewController is interfering with the UINavigationController being able to hide the TabBar.
Is it possible to use Hides Bottom Bar When Pushed to hide the TabBar in this type of setup?
Thanks
Note: I realize that the code above only has one tab. I removed the other tabs for clarity.
I think this is happening because the BannerViewController itself is just a container viewController and it never actually pushes another view controller. The view controllers are pushed within the container.