The current structure of an ipad app im working on is like so - In a navigation based application's view controller I have a tableview on the left side of the view and an IBOutlet connected uiview say View A on the right side (screen is divided in these 2 parts, much like a splitview controller). Clicking any row of the left table adds as subview, a uitableviewcontroller view say View A1 inside View A. Clicking any row in A1 brings up a modalview, say View B. View B now has buttons to bring up another view uitableviewcontroller say View A2. Now the way to bring up View A2 like as per the need, i need to first dismiss the modal View B and show the View A2 added as a subview on top of View A1 but with a back button. Hitting this back now should show the previously dismissed modal uiviewcontroller B, which on dismissing reveals View A1. Now I've managed to get everything working up to the point of showing modal View B, but im out of ideas how to proceed with the rest of the flow. Basic steps i need to put together would be,
Dismiss B
Show A2 over A1
Clicked 'back' in A2
Remove A2 & show B
Dismissed B, show A1.
Any suggestions/ ideas/ code to do this?
I figured it quite a while ago but realised i never updated the answer here. So for anyone else who may have a similar implementation, the way i did it was to save a reference to the modal viewcontroller B in the viewcontroller A1, using it to show & dismiss B. Next was fairly simply to do some delegation to tell A1 when to display A2 and on dismissing A2, to tell A1 to show up the modal viewcontroller B. Took a while to do this but it worked like I wanted. HTH.
Related
Always On Top, Undecorated Navigation with Decorated Stage Below
I'd like to position Stage 1 always on top to act as a navigation bar while I open stages below, but also be able to interact with Stage 2 while Stage 1 has focus. Is this possible?
A related post suggested using setPickOnBounds(), but applying this to both stages doesn't seem right. At the moment it's taking two or more clicks (with one click to switch focus) In order to interact with Stage 2.
This also seemed similar, but hoping JNI code isn't required. I don't have the option to pull in another library at the moment.
I'm trying to make two different custom transition (one fade and one slide from top) within a navigation controller.
The transition works very well the first time but when pop the transitions acting crazy.
I guess that navigationController.delegate is the key but I can't figure it out by myself.
Any help will be greatly appreciated
thanks a lot
******************************** IOS14 QUESTION UPDATE *****************************************
the solution of #Vlad for setting the delegate is working great thanks.
But recently in IOS14 a stack menu appearing when a long press gesture is detected on navigation back button (which allows user to navigate through the navigationcontroller's viewcontrollers stack).
And so the navigationcontroller delegate is setting to the wrong controller when popping two or more controllers.
I am once again asking for your support
Your starting state is in VC A.
After viewDidLoad, the navigationController?.delegate is set to VC A which uses anim1.
When you push to B, you're setting navigationController?.delegate to B, which uses anim2.
When you pop from C to B, anim2 is used as navigationController?.delegate is VC B.
When you pop from B to A, anim2 is used because navigationController?.delegate is still VC B.
When you pop B, navigationController?.delegate is set to nil because the instance of VC B is destroyed.
That is why when you try and push B again, the default animation is used.
Two important pieces of information is that:
viewDidLoad is only called one time when the view has finished loading and not when it appears again after a pop.
navigationController?.delegate can only point to one delegate.
I have UISplitViewController with UITabBarController as its master. UITabBarController contains one UINavigationController with UITableViewController as its root (it is main menu of my app).
After tapping on any cell in main menu, in UISplitViewController's detail part another UITableViewController should be presented (let's call it detail view).
In landscape mode everything works OK.
But in portrait, whet I tap on cell in main menu, the detail view is presented modally, and not pushed, like it supposed to. Also, when rotating from landscape to portrait, the main menu is presented instead of detail view, and after I click on main menu's position to show detail view, it is presented modally with no possibility to rotate or to go back.
Removing UITabBarController and setting UINavigationController as UISplitViewController's master works as I want (in landscape mode we have menu|detail views side by side and in portrait mode controllers behave like they were on regular UINavigationController). But then the UITabBarController is gone.
What I've tried:
every possible segue type - none of them works the way I want
subclassing UIStoryboardSegue to implement custom behavior depending on UISplitViewController's viewControllers param (in portrait mode it has only one view controller - master) - but I couldn't recognise classes (thank you Swift!)
What I want is to do it entirely in Storyboard (OK, custom segues doesn't count) - I want an elegant solution and I refuse to believe it's impossible.
Working on iOS 8 SDK, Xcode 6.2, iPhone 6 Plus
Unfortunately there is no absolutely elegant solution to this one (as far as I've managed to accomplish). Hoping that Apple will eventually sort it out, but in the meantime, this is the nicest way possible:
Place one custom segue instead of Show Detail
In perform method of your custom segue have something like:
- (void)perform
{
MasterViewController *source = self.sourceViewController;
AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
UISplitViewController *splitViewController = appDelegate.splitViewController;
if ([splitViewController.viewControllers count] > 1) {
[source performSegueWithIdentifier:#"showDetail" sender:source];
if (appDelegate.masterPopoverController) {
[appDelegate.masterPopoverController dismissPopoverAnimated:YES];
}
} else {
[source performSegueWithIdentifier:#"showDetailSmallDevice" sender:source];
}
}
[splitViewController.viewControllers count] is here just to separate large devices (iPads & iPhone 6 Plus) and the other, smaller ones
In your Storyboard, wire up one segue named showDetail which is actually a showDetail, to the detail navigation controller, and directly to the contents view controller another showDetailSmallDevice which is actually Show
(Push)
See the example:
http://i.stack.imgur.com/GQpg3.png
EDIT: SplitViewController needs two Navigation Controllers. The solution is that you need to insert another Navigation Controller between the SplitViewController and the DatailViewController. Then, from the TableView, preform a Segue directly to the second Navigation Controller. The SplitViewControllers wants two Navigation Controllers...
Maybe a good way could be to start a new SplitViewController project on IB. There are various default methods and properties to manage a SplitViewController. You can find something in appDelegate class, it could be a good starting point.
OLD: I like Mateusz's answer, just a point that is possible to use self.splitViewController.isCollapsed for testing if DetailViewController is or it could be shown on screen. With this property there is no need to count viewControllers.
#property(nonatomic, readonly, getter=isCollapsed) BOOL collapsed
From documentation: A Boolean value indicating whether only one of the child view controllers is displayed. This property is set to YES when the split view controller content is semantically collapsed into a single container. Collapsing happens when the split view controller transitions from a horizontally regular to a horizontally compact environment. After it has been collapsed, the split view controller reports having only one child view controller in its viewControllers property.
I have 2 questions about this storyboard test project. I am new to Xcode, and I can't find solution to this problem.
This is Storyboard setup
View Controller A is Root View Controller. View B and View C extend from it separetely. Table View extends from View C. View B has 2 buttons - To Table View and to View B.
(I forgot to add textField on View B, and segue from B to A)
1) Button To Table View pushes Table View. Table Cell contains a string. Pressing the cell, view goes back to View Controller C and that string is displayed in text Field.
problem 1: if I use modal segue from table view to view C textField will be updated with method prepareForSegue, but I will lose Navigation Bar on view C.
problem 2: if I use push segue from table View to View C, back button on view C will not point to view A, it will point to table View.
Solution?
Click on the text field to select it, then press back button to update view C. But how to implement?
Or is there better solution?
2) I want to press button on View C to go to view B. If I use push segue, View B Back button will point to view C. If I use modal push, view B loses Navigation bar.
Can I somehow make push segue to View B, that it's back button points to view A?
[EDIT]
to pass data between view Controllers, I used NSUserDefaults. Turns out that it is very efficient way of passing simple data (strings, numbers, etc) between Views
hot to use it for MODAL segue? in desired tableViewController add in the
-(void)tableview:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
//define user defaults
NSUserDefaults *defaults = [NSUserDefaults standardDefaults];
NSString *testString = #"test";
[defaults setObject:testString] forKey:#"test1"];
[defaults synchronize];
//dismiss ViewController
[self dismissViewControllerAnimated:YES completion:nil]; }
if you wish to use push segue to dismiss view controller and skip navigation sequence (drop the view from sequence) replace
[self dismissViewControllerAnimated:YES completion:nil];
with
[self.navigationController popViewControllerAnimated:YES];
I will update this answer as we get through each problem.
If you are using the table view as a means to make a selection then you should instead Dismiss the table view controller instead of pushing a new view modally.
//In the table view controller's on cell selected method
[self dismissViewControllerAnimated:YES completion:^{
//code
}];
Pushing views will result in the the next view being placed on top if you want to get back to view A from view C (Provided you presented it modally) you can use the same code above to get back from C to A
Basically in this case:
View A --modal-> View C --modal-> TableViewController
Then you have to call the above code once in TableViewController and once again in ViewController C
and bam back to A
As far as having B point back to A it's easier if you go from A to B However if you never really need to go from A to B I suggest changing up the structure.
But to fulfill your request one method of switching your view hierarchy is by dismissing view C while at the same time pushing B on top of A.
//Inside View C If you want it to happen only after the first animation completes just move the other line up into the block
[self dismissViewControllerAnimated:YES completion:^{
//code
}];
[self.parentViewController.navigationController pushViewController:<#(UIViewController *)#> animated:YES];
I hope this is helpful.
my Question is quite simple.
I have an add-button. When I tap on it --> presentmodelviewController presents a UIViewController, which contains a simple Table with cells.
When I tap on a Cell, i want to display a new View using pushViewController, which automatically creates a "back Button".
At the top of it in this new View i have a Textfield, where I can enter some Text.
When I tap the back-button, the view slides back to the add-View (which was presented using modalView...).
Now i want the text edited in the view before to be placed in the Label of the first row (cell) on which I tapped.
So I want to do this for 5 cells. Each of them presenting another xib.
Please, can anyone help?
Thanks for your helpful replies.
You should first present a modalviewcontroller that has a navigationcontroller within. Within this view, you can now push other view controllers.