This code works perfectly to switch view controllers,except the tab bar controller disappears.
Now I try many different variations of this code
[self presentViewController:homeNavigationController animated:NO completion:nil];
But none of them seems to work properly. The push controller just freezes the view in place. Any tips on what to do?
- (void)_tabBarItemClicked:(id)item {
assert([item isKindOfClass:[UIButton class]]);
NSInteger selectedIndex = ((UIButton *)item).tag;
[self setSelectedIndex:selectedIndex];
[self _setSelectedItemAtIndex:selectedIndex];
NSDictionary *userInfo = #{#"index": [NSNumber numberWithInt:selectedIndex]};
[[NSNotificationCenter defaultCenter] postNotificationName:#"tabBarDidSelectItem" object:nil userInfo:userInfo];
if (selectedIndex ==2) {
HomeViewController *homeViewController = [[HomeViewController alloc] initWithNibName:nil bundle:nil];
UINavigationController *homeNavigationController = [[UINavigationController alloc] initWithRootViewController:homeViewController];
[self presentViewController:homeNavigationController animated:NO completion:nil];
}}
You're presenting homeNavigationController modally -- what you're seeing is the normal behavior of a modal view controller, that is, they take over the whole screen including the tab bar. If you want to see the tab bar, then don't use a modal presentation.
I solved this problem by:
1) Define YourTabBarController object in AppDelegate
2) And presentViewController from YourTabBarController's object instead of 'self' like
[appDelegateObj.yourTabBarObj presentViewController:homeNavigationController animated:NO completion:nil];];
Make sure your Appdelegate object is initialized.
Related
Background: I would like to dismiss a modalView that I have presented earlier and right away present the same viewController that I just dismissed with new information.
Problem: I have not been very successful in doing so without an explicit pointer to the parent ViewController that presented the first ViewController modally. I am trying to write this class that works without messing around with the previous viewController's code.
Possible lead: There are couple of things I have been experimenting with:
1.) Trying to get access to the parent ViewController, which at this time I don't know how to.
2.) Once access to the parent is gained, I can simply apply the following code:
UIViewController* toPresentViewController = [[UIViewController alloc] init];
[self dismissViewControllerAnimated:YES completion:^{
[parentViewControllerAccessor presentModalViewController:toPresentViewController animated:YES];
}];
In theory this should work given the access to parent viewController. I am open to other ways of doing this.
Assumption: You do not have permission to change any code in the parent ViewController.
Your code looks like it should work. If you are using iOS 5 there is a UIViewController property called presentingViewController.
#property(nonatomic, readonly) UIViewController *presentingViewController;
So you can use this property to get the view controller that presented your modal controller.
Note: In iOS 4 parentViewController would be set to the presenting controller, so if you are supporting both iOS 4 and 5 you will have to check the OS version first to decide which property to access. In iOS 5 Apple have fixed this so that parentViewController is now exclusively used for the parent of contained view controllers (see the section on Implementing a Container View Controller in the UIViewController documentation).
Edit: Regarding accessing self.presentingViewController from within the block: By the time the block is called (after the modal view controller is dismissed) the presentingViewController property may get set to nil. Remember that self.presentingViewController inside the block gives the value of the property when the block is executed, not when it was created. To protect against this do the following:
UIViewController* toPresentViewController = [[UIViewController alloc] init];
UIViewController* presentingViewController = self.presentingViewController;
[self dismissViewControllerAnimated:YES completion:^
{
[presentingViewController presentModalViewController:toPresentViewController animated:YES];
}];
This is necessary not because self is gone/dismissed (it is safely retained by the block), but because it is no longer presented, therefore its presentingViewController is now nil. It is not necessary to store the presentingViewController anywhere else, the local variable is fine because it will be retained by the block.
You could accomplish this using notifications.
For example, fire this notification from outside the modal view when you want it to be dismissed:
[[NSNotificationCenter defaultCenter] postNotificationName:#"dismissModalView"
object:nil
userInfo:nil];
And then handle that notification inside your modal view:
- (void)viewDidLoad {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(dismissMe:)
name:#"dismissModalView"
object:nil];
}
- (void)dismissMe:(NSNotification)notification {
// dismiss it here.
}
the solution for ios5:
-(void)didDismissModalView:(id)sender {
// Dismiss the modal view controller
int sold=0;
if(sold==0){
//Cash_sold.delegate = self;
// Cash_sold.user_amount.text=[NSString stringWithFormat:#"%d",somme];
Cash_sold = [[CashSoldview alloc] initWithNibName:#"CashSoldview" bundle:nil];
CGRect fram1 = CGRectMake(200,20,400,400);
Cash_sold.view.superview.frame = fram1;
Cash_sold.view.frame=fram1;
Cash_sold.modalTransitionStyle= UIModalTransitionStyleCoverVertical;
Cash_sold.modalPresentationStyle=UIModalPresentationFormSheet;
UIViewController* presentingViewController = self.parentViewController;
[self dismissViewControllerAnimated:YES completion:^
{
[presentingViewController presentModalViewController:Cash_sold animated:YES];
}];
}
}
Try the following code:
[self dismissViewControllerAnimated:NO
completion:^{
// instantiate and initialize the new controller
MyViewController *newViewController = [[MyViewController alloc] init];
[[self presentingViewController] presentViewController:newViewController
animated:NO
completion:nil];
}];
Okay, working on a transition between a view with a tabbar and another view which is to be an information/about view. I have the code to transition from the view with tabbar and to transition back to previous view, but during the transition back I lose the tabbar at the bottom. Not sure exactly how to approach this with the tabbar in the MainWindow.xib
E.g.:
(IBAction)backButtonPressed:(id)sender
{
TablesViewController *tvc = [[TablesViewController alloc] initWithNibName:#"TablesView" bundle:nil];
tvc.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentModalViewController:tvc animated:YES];
[tvc release];
}
Thanks,
np
Try presenting the modal transition from the containing instance of UITabBarController and not the UIViewController the action was triggered from.
- (IBAction)backButtonPressed:(id)sender
{
TablesViewController *tvc = [[TablesViewController alloc] initWithNibName:#"TablesView" bundle:nil;
tvc.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self.tabBarController presentModalViewController:tvc animated:YES];
[tvc release];
}
I had the exact same problem, did a ugly solution:
- (IBAction)backButtonPressed:(id)sender {
[self.navigationController dismissModalViewControllerAnimated:YES];
}
I am having a little problem -
(BTW i have looked on
How can I present a modal view controller after selecting a contact?
but it didnt help me)
Basically i want to let the user select a contact using the - peoplePickerNavigationController. after the selection i want to presentModalViewController that will use the personRef data.
i can see that the "add person" method get called but the iphone does not present the view.
UPDATE - It works if i cancel the animation in the Dismiss dismissModalViewControllerAnimated and in the presentModalViewController, but then it looks pretty ugly.
this is the function called after the user selects the contact -
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)personRef {
TempREcordId = ABRecordGetRecordID(personRef);
BOOL hasDeleteDate = [GlobalFunctions CheckToSeeIfInHiBye:TempREcordId];
if (hasDeleteDate) {
[GlobalFunctions alert:NSLocalizedString(#"", #"") ];
}else{
[self addCustomValuesAfterSelection];
[self dismissModalViewControllerAnimated:YES];
}
return NO;
}
this is the function called but still the view is not presenting -
- (void)addPerson {
NSLog(#"#2");
AddViewController *addViewController = [[AddViewController alloc] initWithStyle:UITableViewStyleGrouped];
addViewController.delegate = self;
// Create a new managed object context for the new book -- set its persistent store coordinator to the same as that from the fetched results controller's context.
NSManagedObjectContext *addingContext = [[NSManagedObjectContext alloc] init];
self.addingManagedObjectContext = addingContext;
[addingContext release];
[addingManagedObjectContext setPersistentStoreCoordinator:[[fetchedResultsController managedObjectContext] persistentStoreCoordinator]];
addViewController.person = (Person *)[NSEntityDescription insertNewObjectForEntityForName:#"Person" inManagedObjectContext:addingContext];
addViewController.hiByeGroupId = [dataSource hibyeGroupId];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:addViewController];
[self.navigationController presentModalViewController:navController animated:YES];
[addViewController release];
[navController release];
}
thank you very much.
Just don't dismiss the people picker and present your controller modally on top of it. If you afterwards dismiss your controller at some point dismiss the people picker instead (from the caller/parent) and your ViewController will be dismissed too.
From the Apple Docs:
dismissModalViewControllerAnimated: …
If you present several modal view controllers in succession, and thus build a stack of modal view controllers, calling this method on a view controller lower in the stack dismisses its immediate child view controller and all view controllers above that child on the stack. When this happens, only the top-most view is dismissed in an animated fashion; any intermediate view controllers are simply removed from the stack.
Although by picking a person, the picker dismisses, the key is to dismiss it yourself in the delegate callback, after picking a person and than present your controller
- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController*)peoplePicker didSelectPerson:(ABRecordRef)person {
[self.navigationController dismissViewControllerAnimated:YES completion:^{
ContactDetailViewController * vc = [[ContactDetailViewController alloc] initWithWithABRecord:person];
vc.delegate = self;
UINavigationController * nc = [[UINavigationController alloc] initWithRootViewController:vc];
[self.navigationController presentViewController:nc animated:YES completion:^{
}];
}];
}
I suppose you just have to wait until the people picker disappeared by finishing its animation which it indicates by calling viewDidDisappear. If you override and hook up in there, you should be save to present your modal controller.
I have the following code where I display a view controller within a navigation controller.
Just for the test I display it for 3 seconds and then dismiss it.
What is happening is that it disappearing - and then reappearing after a second or so.
What am I doign wrong?
- (void) test
{
[myNavCtrl dismissModalViewControllerAnimated:YES];
}
- (void) viewDidAppear:(BOOL)animated
{
MyViewController *ctrl = [[MyViewController alloc] init];
[ctrl setDelegate:self];
myNavCtrl = [[UINavigationController alloc] initWithRootViewController:ctrl];
[myNavCtrl setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
[self presentModalViewController:myNavCtrl animated:NO];
[ctrl release];
[myNavCtrl release];
[self performSelector:#selector(test) withObject:nil afterDelay:3];
}
The viewWillAppear method is called every time the controller's view appears so you've created a loop. The view appears, it calls the modal view which covers the calling view. When the modal view disappears, the calling view controller's viewWillAppear gets called again. Lather, rinse, repeat.
here's my code:
ViewController *vc = [[ViewController alloc] initWithNibName:#"TableView" bundle:nil];
[self.navigationController presentModalViewController:vc animated:YES];
//[self setView:[vc view]];
If I call it, nothing happens. However, if I change it to:
ViewController *vc = [[ViewController alloc] initWithNibName:#"TableView" bundle:nil];
//[self.navigationController presentModalViewController:vc animated:YES];
[self setView:[vc view]];
The view appears just fine (without the transition, of course).
What am I doing wrong? Is there anything special you have to take care of when initializing the view controller? I tried to copy as much as possible from Apple's examples, but I can't get this to work...
Thanks for any input!
-- Ry
You can only present modal view controllers from controllers that have already been shown onscreen (usually through a UINavigationController or UITabBarController). Try creating a UINavigationController, pushing a viewController to it, and then presenting your modal controller. There's a starter project in Xcode that shows how to create a UINavigationController-based flow if you're unfamiliar with it.
One other thing to note: if you haven't pushed the view controller onto a UINavigationController, the .navigationController property will be nil, and messaging it will have no effect.
I encountered the same problem while attempting to show a modal view over another modal view. Ben's answer is correct, and can be implemented like so:
#interface FirstView: UIViewController {
UIViewController *firstView;
}
- (IBAction)showOptionsView:(id)sender;
#end
In the main view class:
- (void)viewDidLoad {
[super viewDidLoad];
firstView = [[UIViewController alloc]init];
[firstView setView:self.view];
[firstView setModalTransitionStyle:UIModalTransitionStyleCoverVertical];
}
- (IBAction)showOptionsView:(id)sender {
OptionsView *optView = [[OptionsView alloc]initWithNibName:#"OptionsView" bundle:nil];
if(firstView != nil) {
[firstView presentModalViewController:optView animated:YES];
[optView release];
}