I have an issue, viewWillAppear method in the UIViewController which is added to the screen by presentModalViewController method does not "go into" viewWillAppear method. Only time this method is invoked is together with the viewDidLoad, the first time.
- (IBAction)openModal:(id)sender {
if (self.nvc == nil) {
ModalViewController *vc = [[ModalViewController alloc] init];
self.nvc = vc;
[vc release];
}
self.nvc.segmentedIndex = [[self.navigationController.viewControllers objectAtIndex:0] index];
[self presentModalViewController:self.nvc animated:YES];
}
The property is of type retain.
Thanks in advance.
right, it works different and it now goes into viewWillAppear only once. So if you want to change the appearance of your view after dismissing a modal view you should do it using a modal delegate pattern. See the link:
http://useyourloaf.com/blog/2010/5/3/ipad-modal-view-controllers.html
Though it's for iPad, but you can get the idea. In the latest iOS versions it works the same.
Hope it helps
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];
}];
navigated from one view to another will and when i pop my view back viewWillAppear method is not calling.
can you please let me know the reason.
When you load View the first time viewWillAppear method is called? try to use
[[self navigationController] popViewControllerAnimated:TRUE];
to return back
It's typical that these problems are caused by improper use of view controller containment. You need to look at your view controller hierarchy and research the following methods:
[UIViewController addChildViewController:];
[UIViewController removeFromParentViewController:];
[UIViewController transitionFromViewController:toViewController:duration:options:animations:completion:]
[UIViewController willMoveToParentViewController:]
[UIViewController didMoveToParentViewController:]
Read the Implementing a Container View Controller section of the UIViewController Class Reference.
If u are doing all well than ur application is crashed some where, use break point and check , even you can check and follow these steps......
step 1. for push in FirstViewController
SecondViewController *second = [[SecondViewController alloc]init]
[self.navigationController pushViewController:second animated:TRUE];
Step 2. for pop in SecondViewController
//check navigation controller exist in ur application stack
NSArray *arrView = [self.navigationController viewControllers];
NSLog(#"arrView %#",arrView);
for(int i = 0; i <[arrView count]-1, i++)
{
if([arrView objectAtIndex:i] isKindOfClass:[FirstViewController class])
{
[self.navigationController popViewControllerAnimated:TRUE];
}
}
I've also met this situation.
In iOS 5, it's ok.
But when I test in iOS 4.3.1, viewWillAppear is not calling.
So you need call viewWillAppear manually
You can try this
[[self.navigationController.viewControllers objectAtIndex:0] viewWillAppear:YES];
[self.navigationController popViewControllerAnimated:YES];
I am currently developing an iPhone App for my company and i ran into a strange thing.
My View Hierachy looks like this:
UITabBarController containing 5 Tabs with every Tab containing a UINAvigationController.
So far everything works perfect.
Now i want to present a modal View controller via the presentModalViewController method on the
UITabBarController using this lines of code:
-(void)callFilterOptions
{
FilterOptionsView *filterView = [[FilterOptionsView alloc] init];
[filterView setModalTransitionStyle:UIModalTransitionStyleFlipHorizontal];
[self.tabBarController presentModalViewController:filterView animated:TRUE];
}
The FilterOptionsView is a normal UIViewController containing nothing but a black background at the
moment.
What happens is that the view is presented and after a couple of seconds misteriously disappears.
Why is this happening? At no Point i am calling the dismissModalViewController method.
I already ran into this problem when presenting a mailcomposer.
greetings,
Florian
UINavigationController *myNavController = [self navigationController];
[myNavController presentModalViewController:filterView animated:TRUE];
or a better approach might be:
UIApplication *myApp = [UIApplication sharedApplication];
noIBAppDelegate*appDelegate = (noIBAppDelegate*)myApp.delegate;
[appDelegate.tabBarController presentModalViewController:filterView animated:YES];
to dismiss:
UIApplication *myApp = [UIApplication sharedApplication];
noIBAppDelegate*appDelegate = (noIBAppDelegate*)myApp.delegate;
[appDelegate.tabBarController dismissModalViewControllerAnimated:YES];
p.s. I recommend not naming a view controller "filterView" it would be better named "filterViewController"
I created a UIImagePickerController in the viewDidLoad method in my rootViewController.
- (void)viewDidLoad {
[super viewDidLoad];
UIImagePickerController *pickerController=[[UIImagePickerController alloc] init];
pickerController.sourceType=UIImagePickerControllerSourceTypeSavedPhotosAlbum;
pickerController.delegate=self;
[self presentModalViewController:pickerController animated:YES];
[pickerController release];
}
But the view of UIImagePickerViewController didn't appear on the screen.
The SDK version is 4.3
Is there some mistakes i make?
Thanks!
viewDidLoad is called after the view has been loaded and before the view is displayed. viewDidAppear: is called when the view is onscreen and is the correct point to present a modal view controller.
And if you want to do it only once, you might want to consider using a BOOL to keep track of it.
I have a UINavigationController that contains 3 UIViewControllers on the stack.
View A - is the root
View B - is pushed by View A and has `self.navigationItem.hidesBackButton = YES;`
View C - is pushed by View B and has `self.navigationItem.hidesBackButton = NO;`
View C does not show the back button, even though I have hidesBackButton set to NO. How can I resolve this?
Update
A possible bug in 4.2 as it works till 4.1 sdks
I have tried this and mine is working perfectly. I am just posting the implementation of B view controller (BVC) and C view controller (CVC). My initial guess is that you are not setting the title of BVC in viewDidLoad.
#implementation BVC
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.title = #"I am B";
}
- (void) viewWillAppear:(BOOL)animated{
self.navigationItem.hidesBackButton = YES;
}
- (IBAction)pushB:(UIButton *)sender{
CVC *cvc = [[CVC alloc] initWithNibName:#"CVC" bundle:nil];
[self.navigationController pushViewController:cvc animated:YES];
[cvc release];
}
#end
#implementation CVC
- (void) viewWillAppear:(BOOL)animated{
self.navigationItem.hidesBackButton = NO;
}
#end
I think you have to set that property before you push or pop a view controller to affect the next view controller, setting it for the current viewcontroller in viewWillAppear is too late.
Edit: this looks like a bug in 4.2! The back button remains hidden both in the 4.2 simulator and on the device with 4.2, but it works in the 3.2, 4.1, and 4.0 simulators!
Here's the code where when pushing a VC with a hidden back button:
- (IBAction) goto2nd
{
SecondVC *vc = [[[SecondVC alloc] initWithNibName:#"SecondVC" bundle:nil] autorelease];
vc.navigationItem.hidesBackButton = YES;
[self.navigationController pushViewController:vc animated:YES];
}
That is all that should be needed, each VC has its own navigationItem, it's not a global setting, so you don't need to bother undoing it to restore the back button (at least when popping back to a VC where it is set to "NO").
Here's a workaround that I'm using successfully on 4.3.
Instead of hiding the back button, set the left bar button view to an empty view:
UIView *tmpView = [[UIView alloc] initWithFrame:CGRectZero];
UIBarButtonItem *tmpButtonItem = [[UIBarButtonItem alloc] initWithCustomView:tmpView];
[tmpView release];
self.navigationItem.leftBarButtonItem = tmpButtonItem;
[tmpButtonItem release];
To restore the back button, just set the left bar button item to nil:
[self.navigationItem setLeftBarButtonItem:nil animated:YES];
Update: It appears as if the bug is gone in 4.3.
Note: Even though the bug seems to be fixed, I prefer the "empty view" technique because it allows the disappearance and reappearance of the back button to be animated.
The solution for this problem is somewhat tricky..just try it it will surely work since even I faced the same problem.
First set Navigation title in viewWillAppear.
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.navigationItem.title = #"SET YOUR TITLE";
}
When you are navigating to other page just set your navigation title to null.This will not show you any button on top.Since you can get rid of writing
self.navigationItem.hidesBackButton = YES; everytime.
- (IBAction)pushB:(UIButton *)sender
{
SecondVC *vc = [[[SecondVC alloc] initWithNibName:#"SecondVC" bundle:nil] autorelease];
self.navigationItem.title = #"";
[self.navigationController pushViewController:vc animated:YES];
[vc release];
}
I'm running the same issue and it's only happening on the iOS 4.2 simulator, so probably it's a bug on that version.
Reedit:
Try with this, it worked for me:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
self.navigationItem.hidesBackButton = NO;
}
Use the UINavigationControllerDelegate method -navigationController:willShowViewController:animated:. You will implement this in view controller A and view controller B. In A you will set -hidesBackButton: to YES and alternatively to NO in view controller B.
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
viewController.hidesBackButton = YES;
}
You can also use following sample code;
- (void) viewWillAppear:(BOOL)animated{
self.navigationItem.hidesBackButton = YES;
}
- (void) viewWillDisappear:(BOOL)animated{
self.navigationItem.hidesBackButton = NO;
}
If your view heirarchy is really such that View B should not show a back button but View C should, then the simplest way to get around this is to refactor your heirarchy. I'm thinking of the following alternative:
View A calls presentModalViewController:animated: on View B*, a UINavigationController whose view property is View B. View B* pushes View C onto its navigation stack in response to an event (or otherwise) from View B. If you need to jump back to
View A quickly then call dismissModalViewControllerAnimated: on View A. If you want to keep the state of View B* and C in memory then you could also keep another pointer to View B* somewhere so it doesn't go away when dismissed.