I'm looking to have multiple segues through a single UIBarButtonItem button, and depending on the response through the UIActionSheetDelegate, the correct UIViewController would load through a push segue. This is my current code in for the UIActionSheetDelegate.
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0)
{
// rate this app
}
else if (buttonIndex == 1)
{
[self performSegueWithIdentifier:#"bugReportSegue" sender:self];
}
else if (buttonIndex == 2)
{
[self performSegueWithIdentifier:#"featureRequestSegue" sender:self];
}
}
The problem with this is that I cannot link the same button to multiple views through Storyboard segues. I'm wondering if there's a workaround.
EDIT
This is what my code looks like now: (minus the Storyboard)
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0)
{
// rate this app
}
else if (buttonIndex == 1)
{
[self.storyboard instantiateViewControllerWithIdentifier:#"bugReportIdentifier"];
}
else if (buttonIndex == 2)
{
[self.storyboard instantiateViewControllerWithIdentifier:#"featureRequestIdentifier"];
}
}
Instead of using a segue with performSegueWithIdentifier
Consider using the StoryboardID along with instantiateViewControllerWithIdentifier:
To do so, in the Storyboard, simply create a view controller and don't connect any segues to it. In the third tab in the properties inspector, assign it a Storyboard ID:
Then, in your code, you can create an instance like this:
[self.storyboard instantiateViewControllerWithIdentifier:#"ImagePicker"]
This will create a new instance every time though, so you should still save it and re-use it whenever possible.
EDIT: After you get the view controller, you need to present it yourself.
If you are using a NavigationViewController call:
UIViewController * newController = [self.storyboard instantiateViewControllerWithIdentifier:#"ImagePicker"];
[self.navigationController pushViewController:newController];
If not you can use:
UIViewController * newController = [self.storyboard instantiateViewControllerWithIdentifier:#"ImagePicker"];
[self presentViewController:newController animated:YES completion:nil];
Edit 2:
Here is what your final code should look like:
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0)
{
// rate this app
}
else if (buttonIndex == 1)
{
UIViewController * controller = [self.storyboard instantiateViewControllerWithIdentifier:#"bugReportIdentifier"];
[self presentViewController:controller animated:YES completion:nil];
}
else if (buttonIndex == 2)
{
UIViewController * controller = [self.storyboard instantiateViewControllerWithIdentifier:#"bugReportIdentifier"];
[self presentViewController:controller animated:YES completion:nil];
}
}
Related
There are five controllers here, AViewController, BViewController, CViewController,DViewController,EViewController,controllers here,
A present---> B
B present---> C
C push--->D
D push--->E
Now, if I want to go back from EViewController to AViewController in one step, what code should I write?
[self.navigationController popToRootViewControllerAnimated:animated];
1) Getting the desirable ViewController as Below
for (id controller in [self.navigationController viewControllers])
{
if ([controller isKindOfClass:[AViewController class]])
{
[self.navigationController popToViewController:controller animated:YES];
break;
}
}
2) Here you have A,B,C,D,E Controllers. means A would be on 1 Position so what can you do
you can hard wired the Index as Below
[self.navigationController popToViewController:[[self.navigationController viewControllers] objectAtIndex:0] animated:YES];
3) Pop to the first viewController or rootViewController
[self.navigationController popToRootViewControllerAnimated:animated];
Use unwind segues.
In AViewController add bellow code
-(IBAction)prepareForUnwind:(UIStoryboardSegue *)segue {
}
Go to User Interface of EViewController and Ctrl-drag from the button (you want set action) to the “Exit” outlet, you will see a modal popup.
You can do it recursively with generic solution. First of all you should have reference to A's navigation controller and then you should write recursive method to get active navigation controller like :`
-(UINavigationController*)getActiveNavigationController : (UINavigationController*)navigationController {
if ([navigationController.presentedViewController isKindOfClass:[AViewController class]]) {
return [self getActiveNavigationController:(UINavigationController*)((AViewController*)navigationController.presentedViewController)
];
}
if ((UINavigationController*)navigationController.presentedViewController == nil) {
return navigationController;
}
return [self getActiveNavigationController:(UINavigationController*)navigationController.presentedViewController];
}
`
After that you should write method like
-(void)getInitialScreen:(UINavigationController*)AViewControllerNavigationController {
if ([AViewControllerNavigationController.presentedViewController isKindOfClass:[AViewController class]]) {
return;
}
UINavigationController *navigation = [self getActiveNavigationController:AViewControllerNavigationController];
[navigation dismissViewControllerAnimated:YES completion:^{
[self getInitialScreen:AViewControllerNavigationController];
}];
}
finally after you wrote those 2 methods. You can call them like below and you can always get AViewController
[self getInitialScreen:AViewControlelrnavigationcontroller];
[AViewControlelrnavigationcontroller popToRootViewControllerAnimated:YES];
I have already created UI alert and call a function.
UIAlertView *alertView1 = [[UIAlertView
alloc]initWithTitle:#"Test"message:#"Working 1!!"delegate: self
cancelButtonTitle:#"OK"otherButtonTitles:nil];
[alertView1 show];
Method for call newView viewController
- (void)alertView:(UIAlertView *)alertView
didDismissWithButtonIndex:(NSInteger) buttonIndex
{
if (buttonIndex == 0)
{
NSLog(#"Cancel Tapped.");
}
else if (buttonIndex == 1)
{
// NSLog(#"OK Tapped. Hello World!");
UIViewController *newView = [[UIViewController alloc] init];
[self presentViewController:newView animated:YES completion:nil];
}
}
I have created a new class named "newView" and also add "UIAlertViewDelegate" in present view controller.
But my problem is, I couldn't connect the newView viewcontroller with my present view controller.
Here you are creating object in memory so that's why you can now only access properties and public methods of newView. Can not make presentation of newView.
You can achieve this by 2 ways.
Either you can make this possible by calling Segue or you have to create newView object from Storyboard.
ViewController *entryController = [self.storyboard instantiateViewControllerWithIdentifier:#"go"];
[self.navigationController pushViewController:entryController animated:YES];
My app is setup with a Tab Bar Controller as the RootViewController, and each Tab has a NavigationController in it. When certain actions are performed, I want the app to push a ViewController onto the screen. The flow of this is that when the app starts, or opens from background, it checks a stored NSDate and compares it to the current date. If the right condition is met, it shows a UIAlertView. If the button I named "Push" is selected, it runs the code to push the new view. This is the reason I need it to be ran from the AppDelegate, as there is no guarantee what tab may be open if the app is being used in the background. Since every tab contains a NavigationController, I thought I could run this from the AppDelegate:
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (alertView.tag == 100) {
if (buttonIndex == 0) {
//Cancel
NSLog(#"Cancel");
}
if (buttonIndex == 1) {
NSLog(#"OK");
[self.tabBarController.selectedViewController pushViewController:self.newView animated:YES];
}
}
}
I get a warning message that says UIViewController may not respond to -pushViewController:animated. Any suggestions as to what else I could do?
The return type for selectedViewController is UIViewController, so you need to tell the compiler that it's actually a navigation controller. You do that with a cast,
[(UINavigationController *)self.tabBarController.selectedViewController pushViewController:self.newView animated:YES];
Try this!!
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 0) {
NSLog(#"Cancel");
}else{
NSLog(#"Push");
[self loadTabbar];
}
}
-(void)loadTabbar{
UITabBarController *tabbarController = [[UITabBarController alloc]init];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:[NSBundle mainBundle]];
ViewControllerOne *tab1 = [storyboard instantiateViewControllerWithIdentifier:#"ViewControllerOne"];
UINavigationController *navi1 = [[UINavigationController alloc]initWithRootViewController:tab1];
tab1.tabBarItem.title = #"Tab1";
tab1.tabBarItem.image = [UIImage imageNamed:#"1.png"];
ViewControllerTwo *tab2 = [storyboard instantiateViewControllerWithIdentifier:#"ViewControllerTwo"];
UINavigationController *navi2 = [[UINavigationController alloc]initWithRootViewController:tab2];
tab2.tabBarItem.title = #"Tab2";
tab2.tabBarItem.image = [UIImage imageNamed:#"2.png"];
NSArray *tabArrays = [[NSArray alloc]initWithObjects:navi1,navi2, nil];
tabbarController.viewControllers = tabArrays;
tabbarController.tabBar.selectionIndicatorImage = [UIImage imageNamed:#"tabbar_selected.png"];
[self.window setRootViewController:tabbarController];
[self.window makeKeyAndVisible];
}
Comment here if this is the one you are looking forward!!
I'm developing an app in which I need to show a ViewController when I press the "OK" button in an UIAlertView. How I can do that?
I found on here this solution: iOS Dev: Segue by pressing a button in an Alert?, but it didn't work.
xCode says:
the method: presentModalViewController is deprecated
and I found on the web that I should use the method presentViewController.
I tried to do that but it shows me a black screen without any interaction, what's wrong?
I paste here my code, maybe you can help me.
-(void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex != alertView.cancelButtonIndex)
{
PromoViewController *pvc = [[PromoViewController alloc] init];
[self presentViewController:pvc animated:YES completion:nil];
}
}
Thank you
In order to use a segue programatically you need to called performSegueWithIdentifier.
First make sure your segue has an identifier in the storyboard.
Then use this code instead...
-(void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex != alertView.cancelButtonIndex)
{
[self performSegueWithIdentifier:#"YourSegueIdentifier"];
}
}
This will do what you want.
See this: Make button it UIAlertView perform Segue
It will show you how to create a manual segue and call it.
Well another approach is to get the instance and do it programatically as
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"MainStoryboard"
bundle: nil];
PromoViewController *controller = (PromoViewController*)[mainStoryboard
instantiateViewControllerWithIdentifier: #"<Controller ID>"];
[self presentViewController:controller animated:YES completion:nil];
Note controller ID is the storyboard id you set for the scene via attribute inspector
My app has four tabs 3 of them moves to a separate view controller . The fourth one enable the user to log out from the app what i need here is to add an alert message when the fourth tab is pressed can any one help me how to do so ?
I did search for solutions and found nothing .
Thanks in advance
first make sure your appdelegate.h file contains the UITabBarControllerDelegate to be able to access UITabBar methods .. so the definition of your AppDelegate.h should look like this
#interface AppDelegate : UIResponder <UIApplicationDelegate,UITabBarControllerDelegate >
then go to AppDelegeate.m and define a global boolean variable
bool shouldSelectViewController;
this variable decides whether or not your log in screen should be viewed or not .. although we are not going to manipulate this variable in the code but for some reason my code does not work as you wish without adding this variable it does not make any sense but xcode surprises me!
now add this method
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController {
if([viewController.title isEqualToString:#"your log in view controller title"]) {
//TODO show alert here
return shouldSelectViewController;
}
return YES;
}
}
then add a method to transform the user to the log in page if he confirms the alert
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if(buttonIndex == 1) //here I assume that the alert has two buttons 0:cancel 1:Ok
{
// because you are in the AppDelegate you can't access the UITabBarController directly so you get it by writing this line of code
UITabBarController * tabBarController = (UITabBarController *)_window.rootViewController;
NSInteger destinationTabIdx = 3; //this is the index of the tab we want ot transfer the user to
UIView * fromView = tabBarController.selectedViewController.view; //move the user from current view he is in
UIView * toView = [[tabBarController.viewControllers objectAtIndex:destinationTabIdx] view]; // to this view which is view at tab index 3
//now do the transition to the view you want with optional animation
[UIView transitionFromView:fromView toView:toView duration:0.8
options:(destinationTabIdx > tabBarController.selectedIndex ? UIViewAnimationOptionTransitionFlipFromLeft: UIViewAnimationOptionTransitionFlipFromRight)
completion:^(BOOL finished) {
if (finished) {
tabBarController.selectedIndex = destinationTabIdx;
}
}];
}
}
Inside the forth viewController ViewWillappear method show the alertview.When ever it is shown the alert pops out
Use UITabBarControllerDelegate method:
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
if (tabBarController.selectedIndex == 3) {
//show alert here
}
-(void)viewWillAppear:(BOOL)animated
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Alert" message:#"
msg" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
}
//Delegate
- (void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex: (NSInteger)buttonIndex
{
if(buttonIndex==0)
{
self.tabBarController.selectedIndex = 1;
//Move User to the FirstTabBarViewController
}
}
In Your ForthViewController method ViewWillappear use UIAlertView
It may be helpful
When you click the tabbar this method will be called so handle your logic in this method
- (void)tabBarController:(UITabBarController *)rootController didSelectViewController:(UIViewController *)viewController {
}
So if you want to show to the user an alert view when he/she taps on a tab bar item and you don't want to change to the corresponding view controller of the UITabBarItem then you should try this:
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController {
if([viewController isKindOfClass:[TheViewControllerOfYourAlertTab class]) {
//TODO show alert here
return NO;
}
return YES;
}
Also, if you want to show the ViewController of the UITabBar which will show the alert view after the user selects a button from the alert view, you will need an extra BOOL value to be added in the if statement something like:
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController {
if([viewController isKindOfClass:[TheViewControllerOfYourAlertTab class] && shouldShowAlert) {
//TODO show alert here
return NO;
}
return YES;
}
And the shouldShowAlert by default will be YES, when the user selects the required button from the alert view you can do:
shouldShowAlert = NO;
self.selectedIndex = indexOfYourAlertTabBarItem;
Also make sure to set the delegate of your alertView.