I've got a storyboard with view A that is inside a navigation controller. I dynamically add subView B to view A. Subview B has a table view, and the table view cell has a seque (push) to a detail view. When I click on the cell, the prepareForSegue method is called, but the detail view is never displayed. If I switch the seque to a modal, then the detail view gets displayed inside view A, where subView B was.
What I want to happen is the detail view gets pushed onto the navigation controller and when the user hits back on the detail view it goes back to view A, with the subview B embedded.
Below is the code I use for adding the subview:
if(!self.homeViewController){
self.homeViewController = [self.storyboardinstantiateViewControllerWithIdentifier:#"HomeView"];
}
if(self.currentViewController != self.homeViewController)
{
[self.view insertSubview:self.homeViewController.view belowSubview:self.tabBar];
[self.currentViewController removeFromParentViewController];
}
self.currentViewController = self.homeViewController;
Without seeing your code (and storyboard) this may be hard to diagnose. I have found, however, that sometimes it's a chore to get segues to work properly with dynamically loaded content. In some cases I have found that using the pushViewController:animated: and popViewController:animated methods of the UINavigationController can be a better approach. You should be able to access the UINavigationController by through UIViewcontroller.navigationController.
Related
I am using UITableViewController in my applicaton. While pop from tableview controller to back, i was setting nil to table view to deallocate the view controller from memory. its again calling viewDidLoad, please explain me why it is happening.
-(void)handleBackButton{
self.tableView=nil;
[self.navigationController popViewControllerAnimated:YES];
}
You could set a breakpoint in viewDidLoad and look at the stack trace to see why it's reloading its view.
But I can make an educated guess. When you tell the navigation controller to pop a view controller, it needs to animate that view controller's view off the screen. To do so, it probably asks the disappearing view controller for its view.
A UITableViewController's view is the same as its tableView. When you set tableView to nil, you also set view to nil. So when the navigation controller asks the table view controller for its view (so it can animate the view off the screen), the table view controller notices that its view is nil, so it loads its view. And to load its view, it sends itself loadView and then it sends itself viewDidLoad.
I don't know why you would really bother trying to unload the view. If the view controller itself gets deallocated, it will release its view (which will deallocate the view unless you've retained it somewhere else). And if the view controller doesn't get deallocated, isn't that usually because you might want to put its view back on the screen soon?
Anyway, if you really want to get rid of a view controller's view, don't set its view to nil while the view might still be in the on-screen view hierarchy. Wait until the view is definitely out of the hierarchy. For example, subclass UITableViewController, and override didMoveToParentViewController: like this:
- (void)didMoveToParentViewController:(UIViewController *)parentViewController {
[super didMoveToParentViewController:parentViewController];
if (parentViewController == nil) {
self.tableView = nil;
}
}
I have an app with one main TabBarController containing two tabs that control two different views, A & B. View A is a scrollView and View B is a TableView. When i initially load the app, the scrollview in view A is empty.
In order to add pages to my scrollView, I have set it up as follows: I go to view B and perform one modal segue to a view embedded with a navigationBar. The navigationBar only has one button, 'Cancel', which I use to dismiss the view. Otherwise, the user must click on an image an perform another modal segue to a different view. This view has no navigation bar, and has one button 'DONE', which I use to perform a modal segue back to the initial tabBarController.
Here's the problem: the page is added to the scrollView with no errors after I press 'DONE'. However, I believe I now have two instances of the same tabBarController floating around in memory. When I attempt to grab the views contained in the scrollView with a different button, it tells me that it is now empty (even though it was full during viewDidLoad and viewDidAppear).
How can I remove the initial tabBarController view or otherwise how can I segue back to the tabBarController that I have already allocated? Any help would be extremely appreciated! Thanks!
You shouldn't do a segue back to the original view controller. Rather, you should dismiss the current view controllers animated, and show your original tabBarController.
Inside the view you were segueing back from, add:
tabBarController *tabs = (tabBarController*)[[self presentingViewController]presentingViewController];
tabs.selectedViewController = [tabz.viewControllers objectAtIndex:0];
[[[self presentingViewController] presentingViewController] dismissViewControllerAnimated:YES completion:nil];
Then you will have the view A appear and still use the same allocation.
i have two views say A & B. Both are the subclass of UIViewController class..View A is not a Table View but it is a scroll enabled view as it is more than the iphone dimensions 320*460. View B is not a scroll View. I am calling view B while clicking some button in View A like,
-(IBAction)bt:id(Sender)
{
B *mB=[[B alloc]initWithNib:#"B" bundle:nil];
[self.view addSubView:mB.view];
}
the problem is, As View A is larger, therefore when B is loaded over View A, even View A is partially visible in View B.please help me in overcome this problem??
The problem is you are adding view B to View A Subview and View A is in the scroll View so you need create a separate UIView Outlet and UIView in Interface Builder smallViewB the View A whatever size you need to display View B.
Then Add subview to View Outlet you created Above .
Please let me know if the problem persisting.
#interface ViewController A:UIViewController
#property(nonautomic,retain)IBOutlet UIView *smallViewB;
#implementation ViewController A
#synthesize smallViewB; //Make connection smallViewB in Interface Builder.
-(IBAction)bt:id(Sender)
{
B *mB=[[B alloc]initWithNib:#"B" bundle:nil];
[self.smallViewB addSubView:mB.view];
}
Before Adding view B to Main view remove the view A from its superview.
in .h take two objects
ViewA *aObject;
ViewB *bObject;
In View DidLoad create tow objects of View A and View B like this way
aObject=[[ViewA alloc]initWithNibName:#"ViewA" bundle:nil];
bObject=[[ViewB alloc]initWithNibName:#"ViewB" bundle:nil];
[self.view addSubView:aObject.view];
When You want to add View B add this code
[aObject.view removeFromSuperView];
[self.view addSubView:bObject.view];
Similarly IN Back Button action you can add code like
[bObject.view removeFromSuperView];
[self.view addSubView:aObject.view];
Try this code of snippets in your application I hope it will helps you. It wont lost your previous values of calss
Try adding this in you -(IBAction)bt:(id)Sender
ViewA.your_scroll_view.scrollEnabled=NO;
This might be what you wanted to do, if i understood it right.
Thanks for the suggestions but I have founda different solution to my problem.
When adding another view i.e. View B over Scroll View A, I reset the scroll view dimensions of A accordingly so that it is not visible. Also, when I press the Back button in View B, I again set the scroll View dimensions of View A to its previous value. Also, I made View A the delegate of View B since on pressing Back Button in B, I need to call a function which is defined in View A and is a part of View B protocol.
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 am sure this is an easy question, but one that has escaped me for some time now.
Say I have a UIViewController, either defined as a root in an XIB or on a stack. At some point in my code I want to replace it with another view controller. Just flat out replace it. How would I do that?
I have tried defining the controller and assigning, but not sure what actually makes it push on the screen with the absence of a navigation controller.
I think when you say that you want to replace the view controller, what you actually mean is that you want to replace the view. Bear in mind that view controllers aren't visible, but every view controller maps to a view, which can become visible by getting added as a subview of a visible view.
Your solution of replacing self.view with the new view controller's view may work in your particular case, but it's probably not the "correct" answer to your question. There are going to be cases where this solution won't work for you.
Let's say you have a simple view based application with no navigation controller and no tab bar controller. In your app delegate you construct an instance of YourFirstViewController, and you call [window addSubview:yourFirstController];. Your view hierarchy now consists of a UIWindow with a single subview -- the view for YourFirstViewController.
Now let's say the user presses a button on that view, which is handled by an IBAction defined in YourFirstViewController. You want to respond by "replacing" YourFirstViewController's view with a view associated with YourSecondViewController. I put "replacing" in quotes because we more commonly present a view by pushing its view controller onto a navigation stack, or calling presentModalViewController:animated: to present the view modally, but let's assume that you've rejected those options for some reason, and you actually do want to manually replace YourFirstViewController's view with YourSecondViewController's view.
This is a simple matter of manipulating the view hierarchy. You want to remove YourFirstViewController's view from its superview (the UIWindow in this case), and you want to add YourSecondViewController's view as a subview to replace it. Your action would therefore look something like this:
- (IBAction)replaceButtonClicked {
UIView *mySuperview = self.view.superview;
YourSecondViewController *secondController = [[YourSecondViewController alloc] init];
[mySuperview addSubview:secondController.view];
[self.view removeFromSuperview];
[secondController release];
}
When we use a methods like -pushViewController:animated: or -presentModalViewController, the receiving controller manipulates the view hierarchy for us. This may make it seem like we're looking at view controllers on the screen, but we're not. We're just looking at a big hierarchy of nested views going all the way up to a UIWindow at the top.
You can present a new view controller modally:
[self presentModalViewController:aViewController animated:YES];
This won't outright replace the current VC, but it will display a new view over the current view.