I have 2 Views, each View have a ViewController.
I opened the first view early in TabController.
Then (when a line in a table is clicked) I use this to add my subview:
ENSListViewController *vc = [ENSListViewController alloc];
vc.folder_id = 1;
vc.folder_type = #"an";
[vc initWithNibName:#"ENSListViewController" bundle:nil];
[self.view addSubview:vc.view];
[vc release];
In the second view I try to remove this view again, but it ends in a EXC_BAD_ACESS:
- (IBAction)backToFolderList:(id)sender
{
[self.view removeFromSuperview];
}
Where is my mistake?
You are releasing vc by [vc release]; hence it is not getting object of superview..
you have to release it in -dealloc method
Related
I'm not sure how to do this. So I originally had a ViewController that had one .xib, with one main view. I present it like this:
DogViewController *dvc = [[DogViewController alloc] initWithNibName:#"DogViewController" bundle:nil];
dvc.modalPresentationStyle = UIModalPresentationFormSheet;
dvc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:dvc animated:YES];
[dvc release];
So that works fine. However now from a button press in the DogViewController.xib, I want to dismiss the current form sheet, and show another form sheet with some additional questions before proceeding. So I started by adding another view to in my original .xib of DogViewController, then got stuck in the logic of how to dismiss the first one, and show the second one. I'm assuming I need some outlet to the new view in the same .xib, but from there I'm lost. Thanks.
The way to do this would be to set it up with a UINavigationController as Mathiew mentions. However, if you really want to transition between two views on one view controller, you can refer to this sample code from Apple:
http://developer.apple.com/library/ios/#samplecode/ViewTransitions/Introduction/Intro.html
The code uses ImageViews to demonstrate the effect but I don't see why you can't use views instead :)
You can add a view within the other view in front of all of the other objects and just use its hidden property to control whether it's shown or not.
Why don't you use a navigation controller in your modal view, create another xib and do a [self.navigationController pushViewController:secondViewController animated:YES];
If you have a good reason, you can set a second view outlet secondView and use code like
UIView* superview = [self.view superview];
[self.view removeFromSuperView];
[superview addSubview:self.secondView];
Very simple solution is to hold reference to MainViewController and call methods on it that swap between two view controllers.
Like this:
#implementation MainViewController
- (void)showDogViewController {
[self dismissModalViewControllerAnimated:YES];
DogViewController *dvc = [[DogViewController alloc] initWithNibName:#"DogViewController" bundle:nil];
dvc.modalPresentationStyle = UIModalPresentationFormSheet;
dvc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
dvc.mainViewController = self;
[self presentModalViewController:dvc animated:YES];
[dvc release];
}
- (void)showCatViewController {
[self dismissModalViewControllerAnimated:YES];
CatViewController *cvc = [[CatViewController alloc] initWithNibName:#"CatViewController" bundle:nil];
cvc.modalPresentationStyle = UIModalPresentationFormSheet;
cvc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
cvc.mainViewController = self;
[self presentModalViewController:cvc animated:YES];
[dvc release];
}
}
#end
#implementation DogViewController
- (void)showCatViewController {
[mainViewController showCatViewController]
}
#end
#implementation CatViewController
- (void)showDogViewController {
[mainViewController showDogViewController]
}
#end
When I push cancel button in the third view, I want to go back to the first view directly.
I also want to remove the second view.
How can I do that?
This is the code.
// this part is in the first view.
self.second = [SecondController alloc] init];
[self.view addSubview:second.view];
// this part is in the second view.
ThirdController *thirdController = [[ThirdController alloc] initWithStyle:UITableViewStyleGrouped];
self.navigationController = [UINavigationController alloc] initWithRootViewController:thirdController];
[self.view addSubview:navigationController.view];
// this part is in the third view.
- (void)cancel {
[self.view removeFromSuperview]; // this only goes to the second view.
}
EDIT:
Can I use popToViewController in called contoller? My app crashes.
I thought popToViewController can be used only in calling controller.
And popToViewController is used when it was pushed.
I did add not push.
[self.navigationController popToViewController:[[self.navigationController viewControllers] objectAtIndex:0] animated:YES];
popToViewController:animated: is a UINavigationController method that you use when popping view controllers off the navigation controller stack. It doesn't fit for this scenario.
This user is adding subviews, not pushing them on a navigation controller stack.
As a note, it appears as a matter of design you should be using a navigation controller with the first view as the root controller, then the second pushed on the stack, and the third pushed on the stack. Then all you have to do is [self.navigationController popToRootViewControllerAnimated:YES].
I think this will work if you want to keep your current architecture:
// this part is in the third view.
- (void)cancel {
// remove the second view (self.view.superview) from the first view
[self.view.superview removeFromSuperView];
// can't recall, possibly you still need to remove the third view, but i think removing the superview will do it.
// [self.view removeFromSuperView];
}
If you prefer to try the UINavigationController route, then the easiest path is to create a new project in Xcode and select the type for a Navigation-Based Application or a Master-Detail Application. This will create a UINavigationController in a nib and add it to your window. You can then set the root view controller in Interface Builder to your FirstViewController class.
If you prefer to create the UINavigationController in code, then that is also possible. I show that below, along with the rest of the code you need, regardless of whether you create your UINavigationController in a nib in IB or in code.
I also recommend reading the View Controller Programming Guide for iOS.
In your app delegate or some other code:
-(void)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions [
// I would recommend setting up the UINavigationController and FirstViewController as IBOutlets in your nib, but it can be done in code.
FirstViewController* fvc = [[FirstViewController alloc] initWithNibName:#"FirstView" bundle:nil];
UINavigationController* navController = [[UINavigationController alloc] initWithRootViewController:fvc];
[window addSubView:navController.view];
[window makeKeyAndVisible];
[fvc release];
[navController release];
}
In the first view controller:
SecondViewController* svc = [[SecondViewController alloc] initWithNibName:#"SecondView" bundle:nil];
[self.navigationController pushViewController:svc animated:YES];
[svc release];
In the second view controller:
ThirdViewController* tvc = [[ThirdViewController alloc] initWithNibName:#"ThirdView" bundle:nil];
[self.navigationController pushViewController:tvc animated:YES];
[tvc release];
In the third view controller:
-(void)cancel {
// returns to the first view controller
[self.navigationController popToRootViewControllerAnimated:YES];
}
Use
- (NSArray *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated
to go back to a specific view controller.
Try this:
[self.navigationController popToViewController:[self.navigationController.viewControllers objectAtIndex:1] animated:YES];
This will pop to the view at index 1. Hope that Helps!
// this part is in the third view.
- (void)cancel {
self.first = [SecondController alloc] init];
[self.view addSubview:second.view];
}
And I think if you have you don't need to be worried about removing beneath view, later these will removed.
I have an App with one MainWindow.xib file. Then I have ViewControllerA.xib and ViewControllerB.xib. My MainWindow.xib have one ViewController that points two ViewControllerA.xib.
On ViewControllerA I have a button and I would like the button, when pressed, to move ViewControllerB onto the screen. How do I do that?
I tried this code, but I think I am missing something:
- (IBAction)btMyButton:(id)sender
{
ViewControllerB * viewController = [[ViewControllerB alloc] initWithNibName:#"ViewControllerB" bundle:nil];
[[UIApplication sharedApplication].keyWindow addSubview:viewController.view];
[self.navigationController pushViewController:viewController animated:YES];
}
My ViewControllerB does appear, but it is squashed at the top of the screen, over the previous view. Any help is greatly appreciated.
Thank you
Remove the second line:
[[UIApplication sharedApplication].keyWindow addSubview:viewController.view];
You are adding the view twice. The 2nd and 3rd lines both cause the view to be added to the view hierarchy in different places.
--update--
If you remove the 2nd line and are not seeing your view then self.navigationController is most likely nil. Try [self presentModalViewController:] instead.
Make sure that the view of controller B has correct hight you should subtract the navigation bar height 44 px and status bar 20 px as well. Those values are for iPhone.
- (IBAction)btMyButton:(id)sender
{
//you should load from the main app bundle
ViewControllerB * viewController = [[ViewControllerB alloc] initWithNibName:#"ViewControllerB" bundle:[NSBundle mainBundle]];
// you don't need the following line
//[[UIApplication sharedApplication].keyWindow addSubview:viewController.view];
[self.navigationController pushViewController:viewController animated:YES];
[viewController release];
}
Update
As the above comment says if you may don't have a navigation controller to push Controller B into. So Add a navigation controller into the main window instead of the view controller and make its root view controller you Controller A.
I hope this helps you,
you will need to remove old viewcontroller from main windows.
- (IBAction)btMyButton:(id)sender
{
//Assuming you declare two Iboutlet controllerA, controllerB mapping with that view as class variable
{
if (self.controllerB == nil)
{
ViewControllerB * viewController = [[ViewControllerB alloc] initWithNibName:#"ViewControllerB" bundle:nil];
self.controllerB = viewController;
[viewController release];
}
[controllerA.view removeFromSuperview];
[self.view insertSubview:controllerB.view atIndex:0];
}
}
MyPlatesViewController* viewController = [[MyPlatesViewController alloc] initWithNibName:#"MyPlates" bundle:nil ];
[self.view addSubview:viewController.view];
then i delete my viewController
[self.view removeFromSuperview];
but leak instrument shows 20 MB memory
What is wrong ?
You leaked the view controller object. After you remove the view from its superview, you need to release the controller as well.
Alternatively, you can do the following:
[self presentModalViewController:viewController animated:NO];
[viewController release];
Then, when dismissModalViewController is called, both the view and the view controller will be released properly.
You called alloc so it's your responsibility to release it. Your code should look like this:
MyPlatesViewController* viewController = [[MyPlatesViewController alloc] initWithNibName:#"MyPlates" bundle:nil ];
[self.view addSubview:viewController.view];
[viewController release]
Note that your controller is retained by the view when you call addSubview and released when you call removeFromSuperview. So with your current code the retain count of viewController is still 1 after calling removeFromSuperview.
Additionally you should review objective-c memory manament here: http://developer.apple.com/library/mac/#documentation/cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html
I have the following code where I display a view controller within a navigation controller.
Just for the test I display it for 3 seconds and then dismiss it.
What is happening is that it disappearing - and then reappearing after a second or so.
What am I doign wrong?
- (void) test
{
[myNavCtrl dismissModalViewControllerAnimated:YES];
}
- (void) viewDidAppear:(BOOL)animated
{
MyViewController *ctrl = [[MyViewController alloc] init];
[ctrl setDelegate:self];
myNavCtrl = [[UINavigationController alloc] initWithRootViewController:ctrl];
[myNavCtrl setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
[self presentModalViewController:myNavCtrl animated:NO];
[ctrl release];
[myNavCtrl release];
[self performSelector:#selector(test) withObject:nil afterDelay:3];
}
The viewWillAppear method is called every time the controller's view appears so you've created a loop. The view appears, it calls the modal view which covers the calling view. When the modal view disappears, the calling view controller's viewWillAppear gets called again. Lather, rinse, repeat.