How do i set a modal segue (programmatically) to a push segue - xcode

i have an navigation controller in my storyboard, but for one reason i have to make one segue programmatically, but how do i make a push segue programmatically?
this is my code so far:
- (IBAction)nextviewButton:(id)sender {
HolesViewController *Holes = [self.storyboard instantiateViewControllerWithIdentifier:#"HolesViewController"];
Holes.nameString = self.NameField.text;
[self presentViewController:Holes animated:YES completion:nil];
}

Alternatively, I actually prefer to define a segue right in my storyboard, but rather than originating from the button, I have it originate from the view controller itself, e.g.:
Then, give that segue a "storyboard id", say "Details", and then you can invoke that segue programmatically via:
[self performSegueWithIdentifier:#"Details" sender: ...]; // you can specify either the button or `self` for the `sender
I like this because that way, the storyboard continues to visually represent the flow of the app (as opposed to possibly having scenes floating out there with no segues). And you can use the exact same construct for both push and modal segues (and the view controller that's presenting the next view controller doesn't care which one the storyboard uses).

[self.navigationController pushViewController:Holes animated:YES];
Got it

Related

OS X storyboards: using "show" segue without allowing duplicate new windows to show?

Right now I have an OS X storyboard app that has a main window, and a button on it that triggers a "show" segue for another view controller. Right now I've got the segue set up as modal because if I don't, the user could click the same button again and end up with two copies of the same window.
Is there a way for me to accomplish this without having to restructure the storyboard to embed these view controllers in a separate window controller (which would seem to defeat the purpose of the flexibility the storyboards offer)?
Edit: While the answer below does work, it is definitely not the best way. In your storyboard, select the view controller for the destination view then go to the attributes inspector and change Presentation from Multiple to Single. That's it, no code required.
Not sure this is the best way but in the NSViewController that is pushing the segue, you could add a property for the destination NSViewController and, in your prepareForSegue:sender: method, assign the destination view controller. Finally, in the shouldPerformSegueWithIdentifier:sender: method, check to see if the destination view controller is assigned, and, if so, bring its window to the front and return NO meaning don't perform the segue, otherwise, return YES. Here's a quick example (to be included in the NSViewController with the button to initiate the segue):
#interface ViewController ()
#property (weak) NSViewController *pushedViewController;
#end
#implementation ViewController
- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender {
if (self.pushedViewController) {
[self.pushedViewController.view.window makeKeyAndOrderFront:self];
return NO;
}
return YES;
}
- (void)prepareForSegue:(NSStoryboardSegue *)segue sender:(id)sender {
self.pushedViewController = segue.destinationController;
}
#end
When you close the window containing the destination view controller, this will set the pushedViewController property of the original view controller to nil so the segue will perform if the window is not already opened. Again, there may be a better way to do this. Hope this helps.
Jon

Push from UIButton to Navigation Controller

So I have a Navigation Controller (see sketch below) that "houses" a Tab Bar Controller. The Tab bar controller has 4 tabs (views). Now, inside one of those views, I have a UIButton. I WANT to create a Push segue from this button (highlighted) to another view, but I need the view it's pushing to to have Navigation capabilities. That said, as we all know, you can't push to a Navigation Controller. How can I get around this, and push from the UIButton to a ViewController with a Navigation bar?
EDIT:
So far, this is the code used to push from the UIButton to the View Controller.
HomeViewController.h
- (IBAction)favoritesPressed;
HomeViewController.m
- (IBAction)favoritesPressed {
FavoritesViewController *favoritesView = [[FavoritesViewController alloc] initWithNibName:#"FavoritesViewController" bundle:nil];
[self.navigationController pushViewController:favoritesView animated:YES];
}

What is the pattern of navigating between UIViewControllers in iOS?

I have a bunch of UIViewControllers subclasses (let's call them MainForm, DetailForm, MoreMinorDetails). Basically the idea is that AppDelegate class instantiates MainForm, user presses some type of button on MainForm and DetailForm comes up. Then on a button on the DetailForm launches MoreMinorDetails. And of course, I should be able to go back down to the MainForm.
Note that there aren't any UINavigationController objects anywhere in sight.
What is the accepted pattern to move between UIViewControllers in a manner described above?
Or am I going about it in the wrong way?
I'll be happy with either XCode or MonoTouch based explanation.
You can use a UINavigationController and hide the navigation bar:
self.navigationController.navigationBar.hidden = YES;
Then in your button's action just push the next view controller:
-(void)buttonAction:(id)sender
{
NextViewController *nextViewController = [[NextViewController alloc] init];
[self.navigationController pushViewController:nextViewController animated:YES];
}
To go back, use
-(void)goBack
{
[self.navigationController popViewControllerAnimated:YES];
}
To go to a certain view controller (you have to know exactly when it was pushed onto the navigation controller's stack):
-(void)goToViewController
{
[self.navigationController popToViewController:[self.navigationController.viewControllers objectAtIndex:1] animated:YES];
}
Or to pop to your root view controller
[self.navigationController popToRootViewControllerAnimated:YES];
This way, you will obtain the UINavigationController's functionality and keep all the space in the view.
AngryHacker,
My simple suggestion is to follow zoul one. I think the simplest way to achieve what you want it' to create a UINavigationController and use it as a containment controller for other controllers.
So, the way could be create a UINavigationController in the AppDelegate and set it as the rootViewController for your window. When you create a UINavigationController you can pass to it a root controller (in this case MainForm).
In MT it looks like the following (do not trust the code because I've written it by hand)
private UINavigationController navController;
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
navController = new UINavigationController(new MainForm());
window.RootViewController = navController;
window.MakeKeyAndVisible ();
return true;
}
Now, when you launch the app you will see the MainForm's view and will able to allow navigation among different controllers.
For example, within MainForm you can go to DetailForm like:
this.NavigationController.PushViewController(new DetailForm(), true);
The same applies within DetailForm to MoreMinorDetails.
To go one step back, for example from MoreMinorDetails to DetailForm use
this.NavigationController.PopViewControllerAnimated(false);
To go to the the root controller (MainForm) within DetailForm or MoreMinorDetails use
this.NavigationController.PopToRootViewControllerAnimated(false);
About the space, it's not a problem. I guess you have two ways. The first is to move the bar items you have created within the navigation controller bar. In each controller you can decide what buttons make visible or not. The second is to hide completely the navigation bar and use the button you've already created.
In both ways you can attach actions to these buttons and allow the navigation between controllers. Furthermore, if you choose the first you can also hide the back button for your navigation bar.
A simple note to take in mind is the following:
Since the navigation bar is unique for a UINavigationController, the bar will maintains its state for all the controllers you push in the navigation controller. To explain the concept suppose you have two controllers, say A and B. You first push A and in its ViewWillAppear method you hide a button. When you push B, the button still remains not visible. If you want to unhide the button in B, you can play with its ViewWillAppear method (like before) and so on...
If you don't want to play with UINavigationController you should take a look to new view controller containment functionality provided by UIViewController class. This applies only from iOS >= 5. You can obtain the same effect of UINavigationController mechanism but it could be more difficult to achieve.
Hope that helps.

XCode Storyboard: how to create a segue when the segue trigger is not on storyboard

So I started playing with storyboards in XCode 4.3.2. I started with the Master-Detail application (split view application for iPad). In the detail view (named DetailVC) I have a view where I displayed an array of custom views.
The custom views (named GridView) have a tap gesture recognizer which is supposed to handle the tap event on each custom view. Tapping a GridView pushes a view controller show some search results (named SearchResultsVC).
With GridView created in a separate nib file, and the DetailVC and SearchResultsVC reside in storyboard, how can I create a push segue with destination SearchResultsVC? I just created a segue between DetailVC and SearchResultsVC? Is there someway I can trigger this segue programatically from inside the GridView class when tap gesture is recognized????
In the method where you handle the tap use:
[self performSegueWithIdentifier:#"yourSegueIdentifier" sender:self];
In your StoryBoard control drag from your DetailVC to your SearchResultVC and choose what type of segue you would like. Make sure to name your segue identifier the same as the one in the method above in attributes inspector.
I'm gonna try and improve my answer I messed it up I think:
1) In your DetailVC.h create an instance variable for your GridView like this
IBOutlet UIView * gridView;
also create a getter method and an IBAction for your grid view like this
-(UIView *)gridView;
-(IBAction)myGridGotPressed:(id)sender;
2)Now in your DetailVC.m implement your methods like this
-(UIView *)gridView{
if(!gridView){
[[NSBundle mainBundle] loadNibNamed:#"GridView" owner:self options:nil];
}
return gridView;
}
Also implement your IBAction like this
-(IBAction)myGridGotPressed:(id)sender{
[self performSegueWithIdentifier:#"yourSegueIdentifier" sender:self];
}
3) To make this work you need to change the filesOwner class of your GridView to DetailVC and then hook up the outlets and Actions as normal.
I hope that helps.

Hide/Unhide UINavigationbar when the screen is tapped

I'm very new with iOS Development and I have just created one of my first apps, in my .xib file I have a UINavigationBar that I want to hide/show when a part of the screen is tapped by the user (like in the Photo app). I've found some snippets online but I don't know where and how to use those.
I'd appreciate a lot if somebody could give me detailed informations about how to do this.
Add this toggle method anywhere in your UIViewController. This hides on first tap and shows again in second tap.
- (void)toggleNavBar:(UITapGestureRecognizer *)gesture {
BOOL barsHidden = self.navigationController.navigationBar.hidden;
[self.navigationController setNavigationBarHidden:!barsHidden animated:YES];
}
If there is no navigation controller, link the navigation bar with an IBOutlet and replace with
- (void)toggleNavBar:(UITapGestureRecognizer *)gesture {
BOOL barsHidden = self.navBar.hidden;
self.navBar.hidden = !barsHidden;
}
Then add the following in the method -(void)viewDidLoad {}
UITapGestureRecognizer *gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(toggleNavBar:)];
[self.view addGestureRecognizer:gesture];
[gesture release];
If the view where you are going to tap is a UIWebViewController, you have to add the protocol to the view controller and set it as delegate gesture.delegate = self; then add the following:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
This is needed because the UIWebViewController already implements its own gesture recognizers.
Ultimately, you want to send the -setHidden: message to your navigation bar. The easiest way to do this is to make an Outlet and an Action in your in your view controller. Then, in your .xib file, connect the navigation bar to the outlet and some button (even a large, full screen one) to the action.
Outlets and Actions are basic techniques used over and over in iOS
(and Mac) programming, so if you don't understand them, best go read
up on them now. Every beginning iOS/Mac programming book covers this
topic as does Apple's own Getting Started guide (pay particular
attention to the Configuring the View section).
Inside your action, send a message to the outlet like so:
-(void)myButtonAction:(id)sender{
[[self myNavigationBarOutlet] setHidden:YES];
}
This will hide the navigation bar whenever your button is tapped.
(This assumes you have a UINavigationBar in your .xib like you say. These directions will be different if you're working with a UINavigationController that manages its own UINavigationBar)

Resources