I have A UINavigationController which is managing multiple UIViewControllers. When at the top of the view controller hierachy, and when back is pressed, I want to show a UIAlertView to ask the user if they are sure that they want to go back. What is the best way to check if the view is popped?
I think there is no specific message for the back button.
But you can try to subclass UINavigationController and then override the method popViewControllerAnimated:. (I haven't tried it.)
Another option is to create a custom back button of the type UIBarButtonItem and add a target and action for this button.
This can be done by subclassing UINavigationController and overriding
(BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item
{
}
overriding popViewControllerAnimated: is too late to cancel a pop.
I think that the only way that works is taking a screenshot of the view, cutting out the button, and then adding a uibutton to you navigationController bar. Then you set the image that you have cut out to be the buttons image, after that you create an action with just a uialertview. Set your class as Uialertviewdelegate, and pop the viewcontroller when the user presses the ok button using
- (void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex: (NSInteger)buttonIndex {
if (buttonIndex == 0)
{
//pop viewcontroller
}
}
What about using the UINavigationControllerDelegate-Methods like
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
and check if the controller which should get pushed is of that kind that it needs an warning. The other way around would also work!
Related
I would like to know when we are setting setSelectedIndex for uitabbbarviewcontroller,
Which delegate method will be called.
In my app, i have list of songs to purchase.when user taps buy button for any song, i will show the downloading tab.for that i am setting [self.tabBarController setSelectedIndex:3];there i am showing the song details and progressview that how much is downaloded etc.
This is fine upto this.in the meanwhile of downaloding poem the user can go and tap buy another poem.
here i want to reload the tableview.but i dont know in which delegate method i should call reload data for tableview.
I tried viewwillappear and viewdidappear. but these are not called.
So please tell me which delegate method will be called.
Thanks a lot
override UITabBarController setSelectedIndex:
-(void)setSelectedIndex:(NSUInteger)selectedIndex
{
//must call super function.
[super setSelectedIndex:selectedIndex];
[self myMethod];
}
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
{
[self myMethod];
}
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController;
is called only when user taps it, when you programmatically set this, it is not called.
You can fire a custom delegate method or notification as soon as you do it programmatically and do what ever you need to do...
I have scenario in that, On click of Tab I am calling viewWillAppear method and but after that when I press Back button It will directly back without any animation.
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController{
switch(mytabbar.selectedIndex)
{
case 0:
[viewController viewWillAppear:YES];
break;
}
}
All thing working fine but I don't get Back button animation is only issue
You are not allowed to call view controller life cycle methods - like viewWillAppear and viewDidLoad. They automatically called throughout the life cycle of a view as and when needed and applicable.
You need to tell us what exactly you want to implement , then we can help you?
On click of back:
- (IBAction)onBackButtonClicked:(id)sender{
[self.navigationController popViewControllerAnimated:YES];
}
I have a UINavigationController with a UITableView as my main menu. User clicks on a cell and a new view is pushed on the stack. In one case I push another UITableView that needs a toolbar. So on that 2nd tableView's init I setup the self.toolbarItems property with the correct items. But then I need to call [self.navigationController setToolbarHidden:NO animated:YES]; So it makes sense to call this in the viewDidAppear or viewWillAppear method. But I put it in those methods and find out (Also via NSLog) that they never get called. The same goes for hiding it in viewWillDisappear or viewDidDisappear. Why don't these methods get called? Where should I be doing this hiding/showing of the toolbar then?
I have noticed behavior where if a parent controller (like UINavigationController or UITabBarController) never get's viewWill/DidAppear called on it, it won't call it on the child controllers either. So make sure that in the code where you create the parent controller, you call viewWillAppear, show it, then call viewDidAppear. Then it should make those calls on it's child controllers as is appropriate.
Double check the parent controller is having those methods called, and call them yourself if they are not.
Yes Its true
you can do this by first write this code in
- (void)viewDidLoad {
self.navigationController.delegate = self;
}
And then write the code which you want to write in viewWillAppear
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
if ([viewController isKindOfClass:[self class]]) {
//write your code here
}
}
Although you solved your problem, in case someone comes along in the future another problem could have been that you forgot the animated: argument to either method - that is to say, the format of the method needs to look like:
- (void) viewWillAppear:(BOOL)animated
i noticed the same issue in iOS7. When i'm using both tab bar (2 buttons A, B) and navigation controller.
A has two views. One with tableview and second displays data according to the selection from the table view.
B has is the only view.
Button which is refer to another separate view D, placed in both tab bar views (A & B) and in both views of A.
Problem arises when i click the button from tab item B, viewWillAppear and viewDidLoad not called.
So i solved this issue by presentModalViewController:animated: and to come back i used dismissModalViewControllerAnimated:, just when i go to view D from tab item B.
So I have a UINavController in my app and am trying to execute a method when the user presses the back button. I have searched everywhere and can only find bits and pieces that don't really make sense out of context.
Is there a way to implement some sort of check that catches when the user presses the back button to dismiss the current view? (the viewWillDisappear method for the view being popped never gets called for some reason. I did read that it doesn't unless you forward that call?) Does that sound right, and does anyone have any ideas or suggestions? Thanks in advance.
Take a look at the UINavigationControllerDelegate. There are the only two methods that get called when a UIViewController is pushed to the navigation controller stack. Similarly, if one is being pushed then something probably was just popped. This is what I did to call viewDidDisappear and viewWillDisappear.
# pragma mark - UINavigationControllerDelegate Methods
- (void)navigationController:(UINavigationController *)navigationController
willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
static UIViewController *vcPointer = nil;
// If the previous view controller is still around then let's send a viewWillDisappear message
if (vcPointer != nil) {
if ([vcPointer respondsToSelector:#selector(viewWillDisappear:)]) {
[vcPointer viewWillDisappear:animated];
}
}
// Keep track of a pointer to the current viewController
vcPointer = viewController;
[viewController viewWillAppear:animated];
}
This code keeps a pointer reference to the last view controller that was pushed so that once we push another one we can pop the last one (if it still exists).
AFAIK, if you add a UINavigationController to a UIView via code, it won't send those messages to it's subviews by default. It will only do this if the UINavigationController received these calls itself. Maybe this is your problem (I don't know your view setup).
So, when adding the view of the UINavigationController, be sure to manually send it these messages.
UINavigationController *navigationController = [UINavigationController alloc] initWithRootViewController:rootViewController];
[navigationController viewWillAppear:NO];
[aView addSubview:navigationController.view];
[navigationController viewDidAppear:NO];
At least, this is what I found during development. Been searching for this for a long time and I still don't understand the rationale behind it.
You can always hide the default back navigation button and create your own with its own method to be called when pressed.
Execute whatever code you want there then pop the view.
I used this solution:
Add a custom button on the left side in the navigation bar
Let that button activate a custom method.
Disadvantage of this workaround: you will lose that nice arrow shaped "back" button. That can be solved as well with a custom image.
So here is my code.
Put this in your viewDidLoad:
// LeftButton in Navigation Bar
UIBarButtonItem *leftBarButton = [[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStylePlain target:self action:#selector(backButtonPushed:)];
self.navigationItem.leftBarButtonItem = leftBarButton;
[leftBarButton release];
Then add this method in the same .m file:
- (void) backButtonPushed: (id)sender {
// do what you want to do
}
dont forget in the .h file
- (void) backButtonPushed: (id)sender;
The viewWillDisappear & viewDidDisappear is called when a controller is popped or dismissed. The function is called on the fore-front view controller not on the UINavigationController itself. Did you possibly subclass and forget to call the super on something?
I have a navigation based application which I'm trying to add a unique UIToolbar that will be persistent no matter which is the current view, using this:
Persistent UIBarButtonItem in UIToolbar?
The problem is my when I set the frame for the navigationController, the UITableView inside the navigationController shifts 20px under the navigation bar, as if it started drawing behind the status bar.
Any ideas on how I can fix this? I'm stuck!
I ended up using the built-in toolbar of the navigationController.
So on every viewDidLoad I set the current toolbarItems to the same array:
- (void)viewDidLoad {
[super viewDidLoad];
MyDelegate *appDelegate = (MyDelegate *)[[UIApplication sharedApplication] delegate];
[self setToolbarItems:[appDelegate toolbarItems] animated:YES];
}
I don't see any transitions and I could always set it to different buttons if I need to on a specialy viewController.
Maybe this is the way it's supposed to be done. Occam's razor, anyone? :)
I've had this happen a lot when adding sub views to the UIWindow. I tried all sorts of advice from people but eventually just did shifted the frame origin down 20px to accommodate the status bar.
I've made a custom object deriving from UIToolbar, and added a property called staticItems that I populate in the init method with 3 UIBarButtonItem (and their logic)
I've set "Show Toolbar" to my UINavigationController object, and changed toolbar's class to my new one.
Then I've set navigation's parent object as navigation's delegate, and implemented these method
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
[viewController setToolbarItems:downloadToolbar.staticItems animated:NO];
}
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{}
Really close to what you've done, a bit more easy to maintain. Hope will help somebody else.