tabBarController delegate didn't work - ios

I use below delegate method to set the tabBarController not to pop to another sub view controller by setting the return value to NO,
-(BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController {
UIViewController *vc =[((UINavigationController *)viewController).viewControllers objectAtIndex:0];
if ([vc isKindOfClass:NSClassFromString(#"LYAppCategoryViewController")]) {
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"" message:#"" delegate:self cancelButtonTitle:#"" otherButtonTitles:#"", nil];
[alert show];
return NO;
}
else {
return YES;
}
}
but after "NO" was actually returned,the tabBarController still pop to another sub view controller. So it's kinda puzzling,am I getting it wrong, the scenario of using it?
quotes from Apple API "YES if the view controller’s tab should be selected or NO if the current tab should remain active."
thanks a lot for your kind help.

I still didn't get the reason why this happened,but I accomplished my target by adding codes like this:
[tabBarController setSelectedViewController:[[tabBarController viewControllers] objectAtIndex:0]];
[tabBarController setSelectedIndex:0];
tabBarController will not pop to another view controller if "forcing" to pop to the first one.

Related

Push view programmatically from UIAlertView button?

I would open a UIViewController from a UIAlertView button but it doesn't work.
When user terminate a game I show a UIAlertView with some text and two buttons: "Ok" to dismiss alert and "Score" to open the score page.
This is the actual UIAlertView:
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"YOU WIN!"
message:[NSString stringWithFormat:#"You win a game in %d seconds!",seconds]
delegate:self
cancelButtonTitle:#"Ok"
otherButtonTitles:#"Score", nil];
[alert show];
and this is the code for push the view:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
NSString *title = [alertView buttonTitleAtIndex:buttonIndex];
if([title isEqualToString:#"Score"]){
ScoreViewController *score = [[ScoreViewController alloc]init];
[[self navigationController] pushViewController:score animated:YES];
}
}
What I obtain is a completely black screen. Can someone help me? I can't figure it out what I'm doing wrong.
PS: ScoreViewController has a segue from the root view but of course I can't create a new one from storyboard because I want to perform segue programmatically, from the alert view button.
Hope I've been clear, any help will be very appreciate!
It looks like you're instantiating an instance of ScoreViewController and pushing onto your navigation controller. While this is a legitimate way of presenting another controller, it's different from performing a Storyboard segue.
First, obviously, you'll have to make sure you have a segue connecting your view controllers in the Storyboard. It sounds like you've made it that far, so next you'll want to make sure the segue has an identifier. Select the segue and set its identifier in the Attributes inspector. Then perform the segue in code:
[self performSegueWithIdentifier:#"YourIdentifier" sender:self];

Push to ViewController without back button

I am developing an iOS app which contains login/authentication functionality - basically first time a user logins, in they need to enter relevant login details - then they are passed to main app screens - subsequent visits to the app they will be automatically authenticated.
All above works fine - the issue I have is with the Navigation bar - it appears in the main screen in the main part of the app with a back button - I don't want this to be displayed as they should not be able to return to the login screen once authenticated. I guess it's using the root navigation controller which explains the logic, but is there a way to ignore the navigation controller of the login section so the back button is not displayed in the main app.
Below is a screenshot of the structure to help my explanation - left hand group of screens are the login process right hand is the main app structure.
The code used to switch screens is as follows -
SWRevealViewController *swRevealController = (SWRevealViewController *)navVC;
swRevealController.managedObjectContext = self.managedObjectContext;
[self.navigationController pushViewController:controller animated:YES];
Don't push view controller. Create new hierarchy with:
Objective-C
[self.navigationController setViewControllers:#[controller] animated:YES];
Swift
navigationController.setViewControllers([controller], animated:true)
In the Screen which implements after login, the ViewDidLoad method add the line to hide back bar button.
self.navigationItem.hidesBackButton = YES;
Additionally you can add an 'Logout' option as
UIBarButtonItem *backBarButton = [[UIBarButtonItem alloc] initWithTitle:#"Logout" style:UIBarButtonItemStyleBordered
target:self
action:#selector(LogoutClick)];
self.navigationItem.leftBarButtonItem = backBarButton;
-(void)LogoutClick {
[self showLogoutAlert];
}
-(void)showLogoutAlert {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#""
message:#"Do you want to Logout ?"
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Logout", nil];
[alert show];
}
- (void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 1) {
[self.navigationController popToRootViewControllerAnimated:YES];
}
}
Use a modal view controller for the login screen so its not part of your navigation controller hierarchy within your navigation root probably in view did load - sample code below:
- (void) viewDidLoad {
......
LoginVC *loginViewController = [LoginVC alloc] init];
loginViewController.parent = self;
[self presentViewController: loginViewController animated:YES completion:NULL];
return;
}
You may or may not dismiss the modal view from the root - if you do, you will need to be able to call the dismiss routine from loginViewController but there are other ways as well and you can put the dismiss inside the modal view (loginViewController)
(void) login_exit:(BOOL)success {
[self dismissViewControllerAnimated:YES completion:NULL];
if !(success) {
.... send message (UIAlertview and ask if he or she wants to try again)
}
else {
}
return;}
Very simple.. Just navigate to rootviewcontroller
SWRevealViewController *swRevealController = (SWRevealViewController *)navVC;
swRevealController.managedObjectContext = self.managedObjectContext;
//-- I think above lines not needed as per your question
[self.navigationController popToRootViewControllerAnimated:YES];
You need to hide the Navigation Bar in the ViewController before you push the SWRevealViewController by using the below line in viewDidLoad
Objective C
self.navigationController.navigationBarHidden = true;
Swift
self.navigationController?.navigationBarHidden = true;
It will not show the back button in the next view controller pushed
2022 answer
#IBAction func SomeScreen() {
let s = UIStoryboard ...
navigationController?.isNavigationBarHidden = true;
navigationController?.pushViewController(s, animated: true)
}
It's that easy.
Write this in viewDidLoad method
self.navigationItem.hidesBackButton = YES;
This will hide the back button for the first view.
ClassA* controller = [storyboard instantiateViewControllerWithIdentifier:#"ClassAIdentifier"];
if (controller != nil) {
[self.navigationController pushViewController:controller animated:YES];
[controller.navigationItem setHidesBackButton:YES animated:NO];
}
You MUST hide the navigationItem after push, otherwise it will be nil.

How should I present a Modal VIew Controller from TabBarController

I have an app whose initial scene is a tab bar controller with 3 tabs. I created a uitabbarcontroller class and set it to that scene (MainTabViewController).
In that class I call presentLogin from the viewDidAppear method and that method reads:
- (void)presentLogin{
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
if (![prefs stringForKey:#"storedUser"] && ![prefs stringForKey:#"storedPass"]) {
NSLog(#"No user prefs stored");
// BUT WAIT, before all this, lets pop up a view controller for user registration
UIStoryboard* sb = [UIStoryboard storyboardWithName:#"Storyboard" bundle:nil];
ModalViewController *popupController = [sb instantiateViewControllerWithIdentifier:#"ModalViewController"];
[self presentViewController:popupController animated:YES completion:nil];
} else {
NSString *storedUser = [NSString stringWithFormat:#"User:%#",[prefs stringForKey:#"storedUser"]];
NSString *storedPass = [NSString stringWithFormat:#"User:%#",[prefs stringForKey:#"storedPass"]];
UIAlertView *internetAlert = [[UIAlertView alloc] initWithTitle:storedUser
message:storedPass
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"Ok", nil];
[internetAlert show];
}
}
But the modalVC isnt showing for some reason. I get this crash log:
Attempting to begin a modal transition from <MainTabViewController: 0xa55d0d0> to <ModalViewController: 0x15e2b5e0> while a transition is already in progress. Wait for viewDidAppear/viewDidDisappear to know the current transition has completed
I believe you get this error because the tab bar controller is putting the view of the controller in its first tab on screen at the same time you're presenting the modal controller. Instead of presenting it from the tab bar controller, present it in the viewDidAppear method of the controller in the first tab. Call it with no animation to see the modal view controller without seeing the firs tab controller.
Try to add a tiny delay like below:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self performSelector:#selector(presentLogin) withObject:nil afterDelay:0.1];
}
The view of the tabbarcontroller contains the viewHierarchies of the viewControllers that the tab bar itself owns. Maybe something is of because of that. Try to see of you still get the error if you only have one viewcontroller set to the tabbar.

iOS Dev: Segue by pressing a button in an Alert?

I've been searching for a few hours and haven't found any answers, so I would really appreciate your help!
I am designing an app and need to segue to a different view controller when a button in an alert is pressed. I already have the alert set up, but just need the code to segue to a new view.
Try this. create alertview first.
UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:#"Message" message:#"Open New controller?" delegate:self cancelButtonTitle:#"No" otherButtonTitles:#"Yes",nil];
[alertView show];
[alertView release];
Implement the AlertView Delegate Method
#pragma mark AlertView Delegate
-(void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex != alertView.cancelButtonIndex)
{
Viewcontroller *vc = [[UIViewcontroller alloc] initWithNib:#"Viewcontroller"];
[self presentModalViewController:vc];
[vc release];
}
}
Implement the UIAlertViewDelegate and add the method alertView:clickedButtonAtIndex:. Once the right button is clicked, call the method to segue into the new view.
Implement UIAlertViewDelegate and then you get a callback with which button was pressed when the alert was dismissed. Simply call performSegueWithIdentifier in there.
More details at the UIAlertViewDelegate protocol reference

iOS change scene with code

I need to change to another scene after clicking an alert view button.
Here is my code:
(IBAction)confirmar {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Confirmar"
message:#"Confirma que desea recibir notificaciones en su teléfono móvil"
delegate:self
cancelButtonTitle:#"Cancelar"
otherButtonTitles:#"Si quiero participar", nil];
[alertView show];
}
(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:
(NSInteger)buttonIndex {
if (buttonIndex == 1) {
inscrito *cambia = [[inscrito alloc] initWithNibName:#"inscrito" bundle:nil];
[cambia setTitle:#"inscrito"];
cambia.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
// [self.navigationController pushViewController:cambia animated:YES];
[self.navigationController presentModalViewController:cambia animated:YES];
[cambia release];
NSLog(#"Boton 1");
}
}
I'm trying to change to the UIViewController called "inscrito".
I also added: #import "inscrito.h" at top of the file...
I usually use UIViewController, but it appears you might want to push the new viewcontroller
http://developer.apple.com/library/ios/#documentation/uikit/reference/UINavigationController_Class/Reference/Reference.html
Pushing and Popping Stack Items
– pushViewController:animated:
– popViewControllerAnimated:
– popToRootViewControllerAnimated:
– popToViewController:animated:
I think the first code is right, but you need to change this :
[self.navigationController presentModalViewController:cambia animated:YES];
with this :
[self presentModalViewController:cambia animated:YES];
If you don't have navigationController, it won't work.Hope it help

Resources