I have an app that uses the JASidePanel to show a facebook like side menu. It's working great and I can show my left and right panels. But I need the left and right panels to be generic, i.e. if I segue from the current center panel view controller to a new one, say a details view controller, I need to still be able to show my left and right panels.
Consider this scenario with a MainVC and a DetailVC
Scene 1:
[left]-[center]-[right]
|
[MainVC]
Scene 2: upon going to next view controller
[MainVC]
[left]-[center]-[right]
|
[DetailVC]
Scene 3: upon going to another view controller
[MainVC]
[DetailVC]
[left]-[center]-[right]
|
[MoreDetailVC]
The DetailVC is pushed and is "laid on top" of the center panel while the MainVC is still there somewhere on the stack. I need the segues and the push because
I use storyboard
In other view controllers I call popToRootViewController and I need the MainVC to be the rootViewController
I have tried performing a segue from the MainVC to DetailVC
[self performSegueWithIdentifier...];
and at the DetailVC I set the center panel to self like so:
//in view will appear
sidePanelViewController.centerPanel = self;
This produces a black screen for my app. I think this happens because the setter method of the center panel also loads the view controller but the view has already been loaded so it kinda like doubles the segue.
If I remove the line above, the detailVC shows up good, but I can't access the left and right panels.
I've looked at this,
this and
this but
answers have not been given.
I'm thinking this might not be possible with JASidePanel and I'm considering on using other resources.
EDIT:
Instead of performing segue at the MainVC, I tried setting the center panel there directly like so:
sidePanelViewController.centerPanel = [self.storyboard instantiateVCWithIdentifier:#"detailVC"];
And it works, it goes to the DetailVC not via segue so there's no animation but the left and right panels can be accessed. The problem is I cannot return to mainVC using popToRootViewController.
(I need to return to the mainVC in an instant using popToRootViewController because there can be many transitions, its like a home button)
Instead of performing a segue to the next center view controller, I deleted all segues and used:
sidePanelViewController.centerPanel =
[self.storyboard instantiateVCWithIdentifier:#"detailVC"];
This changes the center panel but with no push animation, so that's kinda sad. I then saved a pointer of the main view controller somewhere accessible global, let's say the App Delegate. Then when I pressed the home button, I return home like so:
sidePanelViewController.centerPanel = appDelegate.mainViewControllerPointer;
This returns me to the main view controller in the state that I left it. If I instantiave a new view controller with the [self.storyboard instantiate...] a main view controller is put as center panel without some form data I left it with and that is not what I want
Related
So I've got a UITabBarController as a view in my app, the first tab of which is a UINavigationController. I have a button inside this view that pushes another, custom view onto the stack:
myViewController *vc = [[myViewController alloc] init];
[self pushViewController:myOtherView animated:YES];
The class myViewController has things that are supposed to happen inside of both -viewDidLoad and -viewDidAppear:(BOOL)animated, but if I hit my button right after the UITabBarController view appears, neither of those methods seem to be called. And even stranger, when I hit "Back", the view does not animate away, but rather the view underneath it in the stack just pops back into place.
However, if I go to another tab in the tab bar, then go back to the first tab, then hit my button again, my custom view controller animates in, -viewDidAppear:(BOOL)animated is called, and it animates out of view upon hitting "Back" like it should. Unfortunately, -viewDidLoad is never called.
I'm really trying to get away from using Interface Builder for everything; I want to create this view controller purely programatically, but these weird issues aren't helping. Can anyone think of a reason for this bizarre behavior?
Edit: Even if I create my view controller via IB, this behavior still occurs. What's the deal? Do I need to do something to the UITabBarController?
Edit #2: Here's how I want my views to bet set up:
UITabBarControler
Tab 1: UINavigationController
UIViewController to be pushed onto the stack
UIViewController to be pushed onto the stack
etc (possibly more UIViewControllers)
Tab 2: UIViewController
Tab 3: UINavigation Controller
UIViewController to be pushed onto the stack
UIViewController to be pushed onto the stack
You don't say what kind of object contains the code you posted but, if it's handling a button action, it's probably a custom view controller that's managed by your navigation controller. If that's true, then you'd want [self.navigationController pushViewController:myOtherView animated:YES];.
(If self is some other kind of object or self.navigationController is nil, then you would need to add some more details about your current view controller structure.)
I'm confused on how storyboarding works.
So I created a simple app where the root view controller is a navigation controller.
I dragged a button to the the rootViewController of the NavigationController.
I dragged another view controller onto the screen, made it's background orange, and made it a subclass of OrangeViewController.
I dragged a connection from the status bar area of my rootViewController to the OrangeViewController.
I made this Segue Push and called it ShowOrange.
I created an action for my button that has:
- (IBAction)push:(id)sender {
[self performSegueWithIdentifier:#"ShowOrange" sender:self];
}
That's all it does. So when I press the button, it does show OrangeViewController. Then when I press back however, it keeps my background Orange. The title does change to ViewController, and there is no back button, but the background is orange. I was wondering why it does this?
My other question is a generic question with dragging segues. I seem to be able to drag it from the button itself, or the status bar. Is there a difference? What is really happening when that connection is made? Thanks.
Edit: Picture included
This particular answer is just for your second question:
Dragging from the button is analogous to setting that button's action to be performing the segue. Dragging from the view controller object (which is what I think is happening when you drag from the 'status bar', and would also happen if you dragged from the view controller while more zoomed out, or from the view controller in the list view), you are just setting it up to be used in code (in this case, it must have an identifier. The button segue does not need an identifier).
I am using a UIScrollView with an extended content size and have placed many objects within it. It scrolls like a map. Clicking on a button within the UIScrollView will perform a Segue and takes the user to another Scene (another UIView embedded within a UINavigationController). Within the second Scene, clicking on another button will perform another Segue to bring back to the original Scene (the UIScrollView which scrolls like a map).
Everything works fine, EXCEPT that when it returns to the original Scene, it goes back to the default position. HOW do I make it remember the original position? Imagine that it is a map, and by return to it, it should be showing where it left off and users don't need to re-scroll to the previous place. How can I do that?
I am using Storyboard on iOS 5.
To go back to the previous view, you should not use Segue. Simply use the following line of code:
[self.navigationController popViewControllerAnimated:YES];
The position in the original view should stay as it was. By using Segue to push to another view (no matter to the previous view), you actually create another instance of view controller like this:
VC A -> VC B -> VC A
You can test it by adding another button on VC A and B, and use the above code to verify if your VCs being popped up in the sequence. Your VC A's scroll position is not remembered because a new instance of VC A is created. The first VC A would ever be reachable if you use segue.
First make sure
scrollView.delegate=self;
second in delegate method,remember scrollView.contentOffset.x as class variable
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
self.offsetX = scrollView.contentOffset.x;
}
Third,back from navigation
-(void)viewWillAppear:(BOOL)animated{
CGRect frame=scrollView.frame;
frame.origin.x=self.offsetX;
[scrollView scrollRectToVisible:frame animated:NO];
}
Or change offsetY if scroll vertically
When you perform a segue, that will push the "new" scene on to your navigation stack. If that scene is subsequently "popped" (which would be the default behavior of the UINavigationController's back button in the new scene), the user should be returned to the original view at the desired content offset automatically. If this is not happening, you may accidentally be pushing a new instance of the original view controller. You should not be performing an additional segue, rather you should be popping the top view controller off of the navigation stack. That said, you can use this rather heavy-handed method for making sure the content offset remains regardless:
Before you perform your segue, set the property to the value of your scrollView's contentOffset property, e.g.:
-(void)prepareForSegue
{
[self setScrollViewOffset:self.scrollView.contentOffset];
}
When this view controller prepares to make another appearance, set it's scrollview's contentOffset:
-(void)viewWillAppear
{
[[self scrollView] setContentOffset:self.scrollViewContentOffset animated:NO];
}
To let UIScrollView remember content position between view controller transitions UIScrollView.contentSize should be set correctly before any transition.
Im writing an application which the main view controller is a UIViewController. It has some icons in a grid and I want to dismiss (sliding down) this grid when one of the icons is clicked. This I've done already. The problem is: when the grid is dismisseed I want another View to come from the top of the screen. This view is in this same root view controller. But I want to display the content of other view controllers in this view. For example: I want this view to show a UINavigationController with a UITableView inside it, so the user can navigate through TableViews.
I'm doing this:
HorariosViewController *horarios = [[HorariosViewController alloc] init];
[vuashView addSubview:horarios.view];
HorariosViewController is a UINavigationViewController. It shows me only a blue NavigationBar and changes like self.navigationItem.title = #"Title" won't work.
Thanks!
You can show another view controller's views as subviews but their outlets and actions remain linked to their original view controller unless you write code to make new connections, so self.whatever shouldn't be expected to affect the other view controller's properties.
(Also, if HorariosViewController is a UINavigationController, it shouldn't be created as a UIViewController.)
One approach is to have the navigation controller already there, with the icon grid presented modally on top of it. (you can set the view up this way without animations, so the user doesn't see the navigation controller underneath).
Then, when it's time for the grid to go away, it can call dismissModalViewController on itself with animation.
I've been reading the Head First iPhone Development book and I understand how to get to a new view from a table but how exactly would I be able to get to a new view or view controller, by just simply pressing a button? Is that even possible?
I mean there are some apps where you click a button, not a table cell and it loads a new view. How exactly is that done? If someone could help out a newbie it would be greatly appreciated!
I think what you're looking for is a modal vew controller. THis presents a modal view like you described on top of everything else. If rootViewController is the view controller that is displaying your current view, and myNewViewController the view controller you want to display modally:
[rootViewController presentModalViewController:myNewViewController animated:YES];
There's plenty of examples of this kind of thing on the net, just search for presentModalViewController
Like bpapa said in the comments, it's hard to be specific without code. However, generally what you want to do is:
Build a navigation controller that contains one original view.
Create a button in your original view using the Interface Builder.
Build a callback method (usually defined with IBAction) that is run when the button is pushed.
In that callback method, create a new view and push it onto the navigation controller the same way you would using a table view cell.
Alternately, if you only want one level of hierarchy, you could use a modal view controller; instead of pushing onto the navigation controller in the last step, just present the modal view controller.
The general answer is that you have an object that manages which view controller loads when.
The most commonly used is the UINavigationController. It is a UIViewController that instead of controlling views, controls other view controllers. It works like a simple stack. You push views you want to display onto the nav's controller stack and when you want them to disappear you pop them off.
A common (though sloppy) way of using a nav is to make it a property of your app delegate. Then anywhere in your app you can references it by:
UINavigationController *nav=[[[UIApplication sharedApplication] delegate] navigationController];
The view controller for the first the user sees is held in the nav's topViewController property. If you want to load a view based on a user action in the topViewController.view, you would have something like this:
- (IBAction) loadNextView:(id) sender{ // Action called by a a UI event such as a button press.
UINavigationController *nav=[[[UIApplication sharedApplication] delegate] navigationController];
UIViewController *nextViewController=...// load from nib, connect with IBOutlet, create programmatically
[nav pushViewController:nextView animated:YES];
}
The first view disappears to be replaced by the next one. To return to the first view, you have a method in the next view controller like so:
- (IBAction) unloadSelf:(id) sender{ // Action called by a a UI event such as a button press.
UINavigationController *nav=[[[UIApplication sharedApplication] delegate] navigationController];
[nav popViewControllerAnimated:YES];
}
... and the nav returns you automatically to the previous view regardless of what that view was.
When you first start out, especially if you use Interface Builder, the structure of the app is largely hidden. Behind the scenes all view controllers and their views exist in a hierarchy of some kind that leads back up to the app delegate. You should train yourself to think in hierarchal terms even if it is not immediately obvious how that hierarchy is constructed.