I am having an issue with trying to load a viewcontroller onto another viewcontroller as a subview.
what I have is a NavigationController that loads some viewControllers in as views (pop and push etc) that works perfectly. then I have decided to put a tabBar into a viewController which then looks after all of the selection stuff using a switch statement, this switch statement then calls a method inside one of the viewControllers that appears inside the navigationController.
The method inside this viewController then trys to set another viewcontroller as a subview to the viewcontroller thats inside the navgiation controller.
this is my code.
TabBarViewController.m
#import "DetailViewController.h"
- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item
{
switch (item.tag) {
case 0:
{
NSLog(#"item 1 selected");
DetailViewController *dVC = [[DetailViewController alloc] init];
[dVC tabBarSelectedAction];
}
break;
default:
break;
}
}
so this catches the selected item on the tab bar... then fires off a msg to the DetailViewController method to load the new subview onto DetailViewController.view
- (void)tabBarSelectedAction
{
ButtonOneViewController *b1VC = [[ButtonOneViewController alloc] initWithNibName:#"ButtonOneViewController" bundle:[NSBundle mainBundle]];
[self.testView addSubview:b1VC.view];
}
and this is where I am trying to load the subview onto the screen.. I think I am doing it right but for some reason its not displaying.. another thing I would like to do is animate this view from the bottom of the screen up..
any help would be hugely appreciated.
When you created your new DetailViewController you didn't make it part of the view hierarchy through a push or present type of method. Adding a subview may or may not be working but you won't see it because the object you're adding it to isn't using the screen.
Your method should probably look like this. Assuming self DetailViewController.
- (void)tabBarSelectedAction {
ButtonOneViewController *b1VC = [[ButtonOneViewController alloc] initWithNibName:#"ButtonOneViewController" bundle:[NSBundle mainBundle]];
[self presentModalViewController:b1VC animated:YES];
}
Even with that, I think your logic is a little screwed up. You allocate and initialize DetailViewController but you never present it anywhere. So how are you expecting to see a modal view in DetailViewController, if you never present it.
EDIT: Taking into consideration your comment of adding it to the UINavigationController, you would change it to look something like this..
[[self navigationController] presentModalViewController:b1VC animated:YES];
EDIT2: Also, you're initializing a class, just to call a method which is already self. Your -didSelectItem: method should look more like this.
- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item {
switch (item.tag) {
case 0:
{
NSLog(#"item 1 selected");
[self tabBarSelectedAction];
}
break;
default:
break;
}
}
Related
I'm trying to do a switch view. My first view is a storyboard and i want to switch for view2, i have no problem when click the botton in my first view everything is fine. The prolem is when i am trying to go back, the screen is going black and is not going back to the first view. Here the code that i'm using.
ViewController.h
- (IBAction)View2:(id)sender;
ViewController.m
- (IBAction)View2:(id)sender {
View2 *second = [[View2 alloc] initWithNibName:nil bundle:nil];
[self presentModalViewController:second animated:YES];
}
And here the code that i am using to go back from the second view to the first.
view2.h
- (IBAction)back:(id)sender;
View2.m
- (IBAction)back:(id)sender {
ViewController *second = [[ViewController2 alloc] initWithNibName:nil bundle:nil];
[self presentModalViewController:second animated:YES];
}
Am I doing some kind of error?
Thanks
Your issue is in View2.m
- (IBAction)back:(id)sender {
[self dismissModalViewControllerAnimated:YES];
}
should do the trick
Apple has a View Controller Programming Guide that I suggest skimming through
UPDATE
If you need to jump back more that one ViewController, you should use NSNotificationCenter or keep a reference to the viewController you need to jump back to.
In my experiences, the following line does 1 of 2 things (where self is a subclass of UIViewController)
[self dismissModalViewControllerAnimated:YES];
1) If self has presented another view controller, the line above will dismiss all view controllers that have been presented on top of self
2) If self has not presented any other view controller, the line above will dismiss self back to the previous view controller
I have a view controller inside a tab bar controller. When I'm "inside" the initialized view I want to be able to press the tab bar item again and redraw the view.
My tabbarcontroller is created in the AppDelegate
#AppDelegate.m
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
NSString *titleV = viewController.title;
if (titleV == #"Random") {
DetailViewController *detailViewController = [[DetailViewController alloc] init];
[detailViewController reloadView];
}
}
#ViewController.m
-(void)reloadView{
[self.view setNeedsDisplay];
NSLog(#"view updated");
}
//code
- (void)viewDidLoad
{
[super viewDidLoad];
[self checkContent];
NSLog(#"viewDidLoad");
}
//code
-(void)checkContent{
if (theContent==NULL) {
contentText.numberOfLines=0;
contentText.text = randomContent;
NSLog(#"%#", contentText.text);
} else {
contentText.text = theContent;
}
}
From the log I can see that contentText.text gets updated though the visible label does not until I move to another view and then back again. I'm not sure why this isn't working. Any ideas on how to solve this are greatly appreciated.
If you need more code I'd be happy to provide it.
Cheers,
Dubbelsnurr
Instead of putting - tabBarController:didSelectViewController in appDelegate, I would sub-class my tabBarController and conform to UITabBarDelegate, and call - tabBarController:didSelectViewController from within that.
Here is a tutorial that implements a similar concept:
http://iosdevelopertips.com/user-interface/detect-taps-on-uitabbarcontroller-and-determining-class-type.html
So, I have a tabbarcontroller, and I pass a notification to dismissModalViewController when a particular tabBarItem is touched.
It is working well and the modal View Controller is dismissed. But I want to change it in a particular way, and it does not work as I expect it to...
I have the observer initialized before the notification is posted. These are the tabBarItems -
NSArray *viewControllerss = [[NSArray alloc] initWithObjects: myProfileDataViewController,
sampleViewController,reminderInfoViewController, nil];
[self.tabBarContr setViewControllers:viewControllerss animated:YES];
self.tabBarContr.selectedIndex = 2;
I send a notification on the viewWillAppear of sampleViewController and when I choose that tabBarIcon, it dismisses the TabBarController.
BUT I want the sampleViewController to be on the left most of the UITabBar.
And so I add it like
NSArray *viewControllerss = [[NSArray alloc] initWithObjects: sampleViewController,
myProfileDataViewController, reminderInfoViewController, nil];
THIS DOES NOT DISMISS TAB BAR CONTROLLER.
Note: Please see the order in which NSArray is initialized.
The notification is posted in the viewWillAppear ofsampleViewController` and observer in the respective view controller which presents the modal view controller
Could you put a NSLog right before you post the notification?
See if you get any output when the app loads.
EDIT: Adding onto the answer based on your response
In your sampleViewController could you try this:
Make it conform to the UITabBarControllerDelegate. Your sampleViewController class interface should be something like this:
#interface SampleViewController : UIViewController <UITabBarControllerDelegate>
Then in the .m of your sampleViewController, in the viewDidLoad, set the delegate to be the sampleViewController (self in this case)
-(void) viewDidLoad
{
[super viewDidLoad];
// Assuming you have a reference to your tabBarController somewhere
[self setDelegate:self]; // try this line or the line below
// [[self tabBarController] setDelegate:self];
// The rest of your drawing code here
}
Now implement the delegate method somewhere inside the sampleViewController .m file.
-(void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
{
// I've included this to see if this method actually gets called or not.
NSLog(#"Dismissing modal view controller");
// check to make sure sampleViewController tab was pressed by checking
// the class type of the viewController parameter being passed in
if ([viewController isKindOfClass:[SampleViewController class]]
{
// I assume you have a pointer reference to that modal view controller
// you want to dismiss
[self dismissModalViewController:theUnwantedViewController animated:YES];
}
}
See if that works.
I've a problem with something that seems to be very simple.
My app has a view hierarchy consisting in a UITabBarController containing UINavigationControllers. When I navigate from the root to the second level
I set the hidesBottomBarWhenPushed on true so that the tab bar is hidden
On my firstLevelController:
[secondLevelController setHidesBottomBarWhenPushed:YES];
[self.navigationController pushViewController:secondLevelController animated:YES];
After that when I push to the third level, I bring the tab bar again by doing in the secondLevelController:
[self setHidesBottomBarWhenPushed:NO];
[thirdLevelController setHidesBottomBarWhenPushed:NO];
[self.navigationController pushViewController:thirdLevelController animated:YES];
(I know, I didn't like the [self setHidesBottomBarWhenPushed:NO] either, but it didn´t work otherwise...)
So, here is the problem: when I push the back button in the third level and the second view appears, I need to hide the tabbar again but I couldn´t find the way of doing this.
Any help is appreciated
This is what works for me.
[self setHidesBottomBarWhenPushed:NO];
[thirdLevelController setHidesBottomBarWhenPushed:NO];
[self.navigationController pushViewController:thirdLevelController animated:YES];
[self setHidesBottomBarWhenPushed:YES];
The thirdlevelController shows the tabbar and secondLevelController does not show the tabbar when you pop the thirdLevelController.
On your secondViewController, do :
- (BOOL) hidesBottomBarWhenPushed {
return ([self.navigationController.viewControllers lastObject] == self);
}
This way, the tabbar will always be hidden when you are on the secondViewController, and it will appear on the other view controllers
You can hold a bool value to understand if you are coming from a popViewController
and in viewDidAppear you can detect it an hide your tab bar again.
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
if(backFromThirdView)
[self setHidesBottomBarWhenPushed:YES];
else
[self setHidesBottomBarWhenPushed:YES];
}
I was actually on the same problem. I always tried to hide the tabbar when selecting a row and to disable hiding after returning to the list (a tableview inside a navigationcontroller) so that the user can select the menu again. I set the tabbarcontroller hidden inside the method
-(void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
but when I hided it inside this method, the Tabbar was still hided when returning to my list again. Now I hide the Tabbarcontroller inside the init method of a specific viewcontroller, maybe this works for somebody else too:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
[self setHidesBottomBarWhenPushed:YES];
return self;
}
now when i select a list item and this viewcontroller will be presented the tabbar is hided, after returning to the list it appears again.
You can try this
You declare in the secondLevelController
static BOOL bottomBarShouldHide = YES;
In the viewDidLoad,
if (bottomBarShouldHide) {
[secondLevelController setHidesBottomBarWhenPushed:YES];
bottomBarShouldHide = NO;
}
else {
[secondLevelController setHidesBottomBarWhenPushed:NO];
bottomBarShouldHide = YES;
}
I hope it could help you.
I'd like to use a modal UITableView at startup to ask users for password, etc. if they are not already configured. However, the command to call the uitableview doesn't seem to work inside viewDidLoad.
startup code:
- (void)viewDidLoad {
rootViewController = [[SettingsController alloc]
initWithStyle:UITableViewStyleGrouped];
navigationController = [[UINavigationController alloc]
initWithRootViewController:rootViewController];
// place where code doesn't work
//[self presentModalViewController:navigationController animated:YES];
}
However, the same code works fine when called later by a button:
- (IBAction)settingsPressed:(id)sender{
[self presentModalViewController:navigationController animated:YES];
}
Related question: how do I sense (at the upper level) when the UITableView has used the command to quit?
[self.parentViewController dismissModalViewControllerAnimated:YES];
You can place the presentModalViewController:animated: call elsewhere in code - it should work in the viewWillAppear method of the view controller, or in the applicationDidFinishLaunching method in the app delegate (this is where I place my on-launch modal controllers).
As for knowing when the view controller disappears, you can define a method on the parent view controller and override the implementation of dismissModalViewControllerAnimated on the child controller to call the method. Something like this:
// Parent view controller, of class ParentController
- (void)modalViewControllerWasDismissed {
NSLog(#"dismissed!");
}
// Modal (child) view controller
- (void)dismissModalViewControllerAnimated:(BOOL)animated {
ParentController *parent = (ParentController *)(self.parentViewController);
[parent modalViewControllerWasDismissed];
[super dismissModalViewControllerAnimated:animated];
}
I had quite the same problem. I know the topic is old but maybe my solution could help someone else...
You just have to move your modal definition in a method:
// ModalViewController initialization
- (void) presentStartUpModal
{
ModalStartupViewController *startUpModal = [[ModalStartupViewController alloc] initWithNibName:#"StartUpModalView" bundle:nil];
startUpModal.delegate = self;
[self presentModalViewController:startUpModal animated:YES];
[startUpModal release];
}
Next, in viewDidLoad, call your modal definition method in a performSelector:withObject:afterDelay: with 0 as delay value. Like this:
- (void)viewDidLoad
{
[super viewDidLoad];
//[self presentStartUpModal]; // <== This line don't seems to work but the next one is fine.
[self performSelector:#selector(presentStartUpModal) withObject:nil afterDelay:0.0];
}
I still don't understand why the 'standard' way doesn't work.
If you are going to do it like that then you are going to have to declare your own protocol to be able to tell when the UITableView dismissed the parentViewController, so you declare a protocol that has a method like
-(void)MyTableViewDidDismiss
then in your parent class you can implement this protocol and after you dismissModalView in tableView you can call MyTableViewDidDismiss on the delegate (whihc is the parent view controller).