I have a tabBarController with 5 tabs the third tab is a navigation controller with TableViewController as the root view controller.
When I press on a row on the table view it push a detail view (regular view controller) about the selected row.
The problem is first time parentViewController and presentingViewcontroller properties (in the details page) are set, all other consecutive both properties are set to nil.
EDIT
I created a single tab application with navigation controller same as the one in the picture but I did not disable auto layout in the storyboard, every time parentViewController is set correctly.
I believe this is a bug if you disabled auto layout.
You are neither creating a child view controller, nor presenting a modal.
(Pushing a detail view controller onto a navigation controller's stack is kind of like adding a child, but navigation controllers predate the parent/child view controller mechanism, so they don't use it.)
What you need to check is the navigationController property of your detail view controller. That should be non-nil if it was pushed onto a navigation controller stack.
Related
I've created a view controller that's within the view controller hierarchy of a UINavigationController. This view controller contains a full-frame container view that displays the view of a child view controller.
I'd ideally like to display the items associated with the child view controller's navigation item (i.s., title and rightBarButtonItems) instead of the navigation item of the view controller that contains the container view.
My initial reaction is simply to set viewController.navigationItem = childViewController.navigationItem but navigationItem is read-only. My second reaction is to set the associated items themselves, e.g.:
viewController.navigationItem.title = childViewController.navigationItem.title;
viewController.navigationItem.rightBarButtonItems = childViewController.navigationItem.rightBarButtonItems;
With swizzling, I'm also able to detect when the child view controller's navigation item's properties are set and update accordingly. However, if the child view controller's navigation item's properties are updated without replacement (e.g., title changes text color, rightBarButtonItem is disabled), these changes are not reflected.
Is there any way of achieving the effect I'm looking for?
Hello sir instead of setting childviewcontroller navigation item you can set parentviewcontroller's navigation item.
I mean to say before loading child view controller you can set parentviewcontroller's navigation bar Item if you know childviewcontroller's navigatio bar item value.
I have one more question if you child view controller is inside container how does it have own navigation bar because it would be scrollable so better to set parent view controller's navigation bar before loading child view controller.
Turns out that my problem was elsewhere and that the approach outlined in my question works as desired. x_x
To make this answer more useful, here are more details of my approach:
I created a category on UINavigationItem and swizzled the methods -[setTitle:] and -[setRightBarButtonItems:] using Mattt Thompson's tutorial (http://nshipster.com/method-swizzling/). The swizzled methods simply post custom NSNotifications UINavigationItemTitleDidChange and UINavigationItemRightBarButtonItemsDidChange respectively.
In -[prepareForSegue:sender:] I extract the destination view controller of my embed segue and store it in a custom property childViewController on my view controller.
In the setter for my view controller's childViewController I add observers to my custom UINavigationItem notifications using the navigation item of my child view controller as the object.
When each of these notifications are received, I update the title and rightBarButtonItems of my view controller's navigation item, respectively.
The "elsewhere" in my own fix was that my child view controller wasn't updating its right bar button items when I thought it was, so it appeared as if the view controller presenting it wasn't obtaining its right bar button items.
I've spent the past few days searching on the web for a solution to my problem, however, I can't seem to find a problem similar to mine. I am using a TabBarController and on one of the tabs I have a segmented Control in the navigation bar that I would like to use to switch between view controllers. The problem is that when I present the second view Controller it appears over the tabbarcontroller. Is there anyway to keep the modally presented Navigation controller in the tabbarcontroller?
This is the first controller.
And this is the controller I am trying to present.
well we can't really comment unless we saw some code. But I think your problem may be to do with your view hierarchy. If I was going to build what you are attempting I would do as follows:
UITabbar controller that contains a custom navigation bar controller
The custom nav bar controller would contain the segment controller and have a protocol defined so that a delegate could be alerted when either segment was selected by the user.
The nav bar's root view controller would be a view controller that acted as a UIView container for the two screens you are displaying (friends and circle screens)
This root view controller would be the delegate for the custom nav controller so that it will know when the user selected a segment.
When the user selected a segment the root view controller would then switch between the friends and circles view controllers in the container.
To do the above have a look at the documentation for creating UIViewController Containers and working with delegates
Hope that helps!
I have a hierarchy of 3 TableViewControllers embeded in Navigation Controller and I need to launch on the most detailed level on the top of the hierarchy. If I change 'Is Initial View Controller' in storyboard to the last detailed TableViewController, my app launches with the selected TVC, but with no NavigationBar. How can I launch on the desired level of hierarchy and keep the Navigation Controller managing the stack of views?
Thank you.
You're telling the storyboard that your third view controller is the root view controller--it has no navigation bar. If you want the navigation controller present as the root view controller then you need to make it the initial view controller, then change the navigation's root to your third view controller.
eg:
initial-->[navigation controller]-->[third VC] [first VC]-->[second VC] (keep these around if you want... just disconnect them from the navigation controller)
You would have to select the ViewController that you want as initial and embed it into a NavigationController, and then add all of the other views after that using push segues.
But why do that? Why not just have the first viewcontroller display the data that you will have in the third view controller? you will end up with the same results.
You should also check out this.
I have UITableView with Static cells. I control-drag from one of these static cells to another UINavigationcontroller and select "Push". I notice nothing happen, when I run the app and tap on the static cells.
However, when I do the same thing & choose "Modal" it works fine. Did I miss something?
You can only use a "Push" transition when segueing between view controllers within a parent UINavigationController.
Your Navigation Controller should be your app's initial view controller. Also when your table cell is tapped you'll want to segue to a View Controller (probably a custom UIViewController subclass), not a UINavigationController.
Make sure you have set your storyboard up with the following:
A UINavigationController - this should be set as the Initial View Controller for your app. Check that the checkbox "Is Initial View Controller" is checked in the Attributes inspector pane when the navigation controller is selected in the storyboard.
A UITableViewController - this should be set at your navigation controller's Root View Controller (there should be an arrow pointing from the nav controller to the tableview controller that looks like a segue but has a different icon in the middle)
Another View Controller - this is the view controller you want to segue to when clicking on your table cell, probably a customer UIVewController subclass you've created. Note that it should probably NOT be a navigation controller.
Can someone explain to me what is the exact difference between modal and push segue?
I know that when we use push the segue gets added to a stack, so when we keep using push it keeps occupying memory?
Can someone please show me how these two are implemented?
Modal segues can be created by simply ctrl-click and dragging to destination but when I do that with the push my app crashes.
I am pushing from a button to a UINavigationController that has a UIViewController.
A push Segue is adding another VC to the navigation stack. This assumes that VC that originates the push is part of the same navigation controller that the VC that is being added to the stack belongs to. Memory management is not an issue with navigation controllers and a deep stack. As long as you are taking care of objects you might be passing from one VC to another, the runtime will take care of the navigation stack. See the image for a visual indication:
A modal Segue is just one VC presenting another VC modally. The VCs don't have to be part of a navigation controller and the VC being presented modally is generally considered to be a "child" of the presenting (parent) VC. The modally presented VC is usually sans any navigation bars or tab bars. The presenting VC is also responsible for dismissing the modal VC it created and presented.
Swift 3.0 and XCode 8.2.1 update
1. Push Segue
Push segue has been renamed as Show segue. To create push segue, the parent view controller needs to be embedded in navigation controller. The navigation controller provides navigation bar. Once you connect two view controller with push segue, the child view controller will automatically has navigation bar on top. The child view controller will be added on top of the navigation stack.
Push segue also provides default features. The child view controller will have a back button that gets you back to the parent view controller. You can also swipe right to pop the child view controller. The animation for push segue is like sliding pages horizontally.
While you are allowed to make a push segue from a view controller that is not in a navigation controller, you will lose all the features like navigation bar, animation, gesture etc when you do so. In this case, you should embed your parent view controller inside navigation view controller first and then make push segue to child view controllers.
2. Modal Segue
A modal segue (i.e. present modally), on the other hand, is presenting over the current view controller. The child view controller will not inherit navigation view controller so the navigation bar will be lost if you present modal segue from a view controller with navigation view controller. You have to embed the child view controller in navigation controller again and start a brand new navigation stack if you want it back. If you want to get back to parent view controller, you have to implement this by yourself and call dismiss from code.
Animation for modal segue is that the child view controller will comes up from the bottom of the page. The navigation view controller is also gone in this demo
The push view must be built in a navigationController.
Click on your master view, then in the menu bar choose:
EDITOR->embed in->navigationController
This is pushing controls using custom push and segue methods for storyboard
And Modal is way to navigate through views without using Storyboards.