I'm sure this is some stupid mistake, but i'm trying for the past hour to remove a subview from my superview without any success.
On my first view i'm having
UIViewController *helpView = [[[UIViewController alloc] initWithNibName:#"HelpView" bundle:nil] autorelease];
[self.view addSubview:helpView.view];
And then inside helpView i have a button which is connected to an IBAction called "closeHelp" which just does the following:
- (IBAction) closeHelp{
[self.view removeFromSuperview];
}
But this causes my app to crash with EXC_BAS_ACCESS for some weird reason, even those this is inside the HelpView, meaning self.view should be pointed to the correct subview..
Would appreciate your help
Thank you.
Shai.
As Andreas answered, you are trying to remove self.view from its super/parent view.
You basically need to remove the helpView from its parent view.
so it should be
- (IBAction) closeHelp{
[helpView removeFromSuperview];
}
But we dont know what is "helpView" in the above method. As we dont have any handle for it.
So our code should finally look like this.
#define HELP_VIEW_TAG 101 // Give tag of your choice
HelpView *helpView = [[HelpView alloc] initWithNibName:#"HelpView" bundle:nil];
helpView.view.tag = HELP_VIEW_TAG;
[self.view addSubview:helpView.view];
[helpView release];
- (IBAction) closeHelp{
UIView *helpView = [self.view viewWithTag:HELP_VIEW_TAG];
[helpView removeFromSuperview];
}
The self.view does not point to your subview but the root view which your uiviewcontroller manages. You should probably remove only the last object in the subview stack, not the whole view, because now you are removing the whole help view.
Anyway, why do you not present the viewcontroller modally instead of doing this?
[self presentModalViewController:helpView animated:NO/YES];
helpView. modalTransitionStyle = //One of the constants below
UIModalTransitionStyleCoverVertical
UIModalTransitionStyleFlipHorizontal
UIModalTransitionStyleCrossDissolve
UIModalTransitionStylePartialCurl
Usually I am writing self.modalTransitionStyle = // One of the constants
in the viewcontroller which will be presented modally, instead of spreading the code.
You are initializing helpView as a UIViewController.
Make sure you have #import "HelpView.h" (or whatever the helpView .h file is called) in the .h file of the view controller where you are initializing it.
Then, use this code:
HelpView *helpView = [[HelpView alloc] initWithNibName:#"HelpView" bundle:nil];
[self.view addSubview:helpView.view];
That should fix it.
The easiest solution for me eventually was to just define my XIB's file owner as the same class as the parent controller, meaning the parent controller would control both the parent and the subview, which just makes a lot easier. :)
Declare the help view on calss level.
in.h file
#class HelpView;
..
#interface
{
HelpView *helpView;
}
#property(nonatomic,retain)HelpView* helpView;
In.m file
#import "HelpView"
#synthensize helpView;
now add this Code where you want
helpView = [[HelpView alloc] initWithNibName:#"HelpView" bundle:nil];
helpView.view.tag = HELP_VIEW_TAG;
[self.view addSubview:helpView.view];
- (IBAction) closeHelp{
//UIView *helpView = [self.view viewWithTag:HELP_VIEW_TAG];
[helpView removeFromSuperview];
}
-(void)dealloc
{
[helpView release];
}
Related
I have page-based app. On each page I have 3 uibuttons at the top, uiscrollview with alphabet (uibuttons to sort data in uitable) at the right and uitableview at the center. How to show cell's detail view? If it is necessary to add uinavigationcontroller I can't do this. If I adds it, it disables interaction with my table, buttons and scrollview.
And another question is how to show new data in tableview and scrollview when goes to next page??
I have rootViewController class and DataViewController class.
rootViewController listing:
#interface RootViewController ()
#property (readonly, strong, nonatomic) ModelController *modelController;
#end
#implementation RootViewController
#synthesize pageViewController = _pageViewController;
#synthesize modelController = _modelController;
#synthesize navContr = _navContr;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// Configure the page view controller and add it as a child view controller.
//[self presentModalViewController:navContr animated:YES];
self.pageViewController = [[[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStylePageCurl navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil] autorelease];
self.pageViewController.delegate = self;
DataViewController *startingViewController = [self.modelController viewControllerAtIndex:0 storyboard:self.storyboard];
NSArray *viewControllers = [NSArray arrayWithObject:startingViewController];
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:NULL];
self.pageViewController.dataSource = self.modelController;
[self addChildViewController:self.pageViewController];
[self.view addSubview:self.pageViewController.view];
self.navContr = [[UINavigationController alloc] initWithRootViewController:self.pageViewController];
[self.view addSubview:self.navContr.view];
// Set the page view controller's bounds using an inset rect so that self's view is visible around the edges of the pages.
CGRect pageViewRect = self.view.bounds;
self.pageViewController.view.frame = pageViewRect;
[self.pageViewController didMoveToParentViewController:self];
// Add the page view controller's gesture recognizers to the book view controller's view so that the gestures are started more easily.
self.view.gestureRecognizers = self.pageViewController.gestureRecognizers;
for (UIGestureRecognizer *recognizer in self.pageViewController.gestureRecognizers){
if ([recognizer isKindOfClass:[UITapGestureRecognizer class]]){
[recognizer setEnabled:NO];
}
}
}
After few manipulations it works but I need help to get it work fine!
So now it looks like this
Next question: how do I remove the brown space at the top???
::UPDATE::
Problem solved. It needs just to set y-axis position of UINavigationController to -20 ;)
i'm not sure if this link about creating navigation-based project may help you.. (http://iosmadesimple.blogspot.com/2012/08/navigation-based-project-doing-it.html)
From that tutorial, there's a class called SampleViewController, subclass of UIViewController. You might want to put a tableView in SampleViewController.xib file. Then in your SampleViewController.h file, add an IBOutlet UITableView* yourTable property and synthesize it. Connect it to your tableView in your .xib file. //Or you may do it programmatically
in your SampleViewController.h, make your interface header look like this.. I think you already know this...
#interface SampleViewController:UIViewController < UITableviewDelegate, UITableViewDatasource >
in your SampleViewcontroller.m, under viewDidLoad method, set the table delegate and datasource to self:
yourTableView.delegate = self;
yourTableView.datasource = self;
Afterwhich, you implement tableView delegate and datasource methods... //you already know those since you were already able to show a tableview ;)
one of these methods is the "tableview:didSelectAtIndexpath:" --> this is the part wherein you can put your code when you click one of the cells.
Let's assume you have the DetailsViewController Class, this is the class you would like to show after clicking a cell and show its details.
DetailsViewController Class must have a variable that will accept the data you would like to show. Let's say, an NSString *detailsMessage; //do the #property and #synthesize thing...
Let's go back to SampleViewController.m file, under tableview:didSelectAtIndexpath: Method:
inside that Method.. put these codes.
DetailsViewController *detailsVC = [[DetailsViewController alloc] init];
detailsVC.detailsMessage = #"The Data you want to pass.";
[self.navigationController pushViewController:detailsVC animated:YES];
I hope this helps. :(
There may be other ways but by far the easiest way is to use a navigation controller. In fact, it is built to do exactly this.
If you don't want the navigationBar then you can hide it in the viewWillAppear function.
[self.navigationController setNavigationBarHidden:YES animated:YES];
Then you can add an other UIViewController to push when the user selects a cell.
Having read your OP again I'm not sure how you are adding your navigationController.
To use a navigationController you create it and load it at start time. You then create your current viewController (the one with the buttons and table etc...) and set this as the rootViewController of the navigationController.
Then you display the navigationController.
Could you explain how you are adding your navigationController as it may help understand what is going wrong.
Thanks
::EDIT::
OK, my assumption was correct.
The way you are using the navigation controller is not how it was intended.
OK, so at the moment your AppDelegate file will have a method Application didFinishLaunching...
It will look something like this...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.viewController = [[OJFViewController alloc] initWithNibName:#"MainViewController" bundle:nil];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
You should change it so that it is like this...
first add a property to your appDelegate...
#property (nonatomic, strong) UINavigationController *navigationController;
Then change the didFinishLaunchingMethod to this...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.viewController = [[OJFViewController alloc] initWithNibName:#"MainViewController" bundle:nil];
self.navigationController = [[UINavigationController alloc] initWithRootViewController:self.viewController];
self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible];
return YES;
}
This will still show you MainViewController but it will now be contained within a navigationController.
Next in your MainViewController function viewWillAppearAnimated add the line...
[self.navigationController setNavigationBarHidden:YES animated:animated];
This will then hide the navigationBar at the top of the view so you still have access to your buttons.
The you need a new ViewController and xib file (for example DetailViewController).
When the user selects a table row you need to then do something like...
DetailViewController *detailView = [[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:nil];
//pass in details of which row was selected.
[self.navigationController pushViewController:detailView animated:YES];
This will then display your new view and new viewController. You will also need to write a way of passing the data in (set up a property on the DetailViewController).
Hope this helps.
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
Hi I was wanted to do Application witch have a root template view with a nice logo on top or something adn load other views just below
(here is what I have right now: Test App
)
But I have a little problem. If I'll remove a comment in file TestAppDelegate.m on line 58
//[currentView release];
Application will crash with bunch of errors when I try to switch views.
But if I comment this line Project analyzer is telling me that I have a potential leak
with currentView variable.
Can somebody spare some time and see in that code what I did wrong?
The problem is that you are only adding currentView.view as a subview so that is being retained elsewhere but currentView itself is not. This means that when you release it, it is consequently dealloc'd and its view will have difficulty working without it.
One solution would be to have currentView as an instance variable and create a property for it so that the memory mangement is done for you.
#property (nonatomic, retain) UIViewController *currentView;
and then replace a line like
currentView = [[First alloc] initWithNibName:#"First" bundle:nil];
with
self.currentView = [[First alloc] initWithNibName:#"First" bundle:nil];
This will release the old view controller before retaining the new one. Then lastly don't forget to release currentView in the dealloc method of the class.
I have a function and it looks like this:
- (void) switchView: (int) viewType {
for (UIView *view in [self.viewController.rootView subviews]) {
[view removeFromSuperview];
}
UIViewController *currentView = nil;
switch (viewType) {
case 1:
currentView = [[First alloc] initWithNibName:#"First" bundle:nil];
break;
case 2:
currentView = [[Second alloc] initWithNibName:#"Second" bundle:nil];
break;
}
[self.viewController.rootView addSubview: [currentView view]];
[self.window makeKeyAndVisible];
//[currentView release];
}
I wanted to create a very simple method that switches between views in a view based application. For some reason, when the views are switched, the first view is removed and instead of viewing the second view, I see a white screen.
This is my method:
FirstViewController *firstViewController = [[FirstViewController alloc] initWithNibName:#"FirstViewController" bundle:nil];
self.view = firstViewController.view;
[firstViewController.view removeFromSuperview];
[firstViewController release];
secondViewController = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
self.view = secondViewController.view;
I don't know why it is happening because I know that the second view's ViewDidLoad method is called (I put a NSLog there) - but the second view is not seen!
Any suggestions?
Thanks in advance,
Sagiftw
viewDidLoad's executing because initWithNibName:bundle: calls it. That doesn't mean that the view's actually being displayed.
I usually use this (removing initialisation/release logic):
[self.view addSubview: firstViewController.view];
[firstViewController.view removeFromSuperview];
[self.view addSubview: secondViewController.view];
I am very new to Obj-C and learning iphone development.
My question is how to add subview from app delegate.
Lets say I added subview called "MainView" from "applicationDidFinishLaunching" method.
- (void)applicationDidFinishLaunching:(UIApplication *)application {
MainViewController *aViewController = [[MainViewController alloc] initWithNibName:#"MainView" bundle:nil];
self.mainViewController = aViewController;
[aViewController release];
[window addSubview:mainViewController.view];
// Override point for customization after application launch
[window makeKeyAndVisible];
}
"MainView.xib" file has a button to show its child view. When the button is clicked, it calls "showChildView" method.
- (IBAction)showChildView:(id)sender {
if (self.childViewController == nil) {
ChildViewController *childController = [[ChildViewController alloc] initWithNibName:#"ChildView" bundle:nil];
self.childViewController = childController;
[childController release];
}
[self.view insertSubview:childViewController.view atIndex:0];
}
From this code, when app launches, it shows "MainView" with a button. But when I clicked the button, the button is still visible as well as the content from the "ChildView.xib" file too.
How can I hide the "MainView" when I pressed the button and show only the contents of the "ChildView"?
Thanks for your help in advance.
well, you have to remove the original view first, before inserting the new subview, do it this way
- (IBAction)showChildView:(id)sender {
if (self.childViewController == nil) {
ChildViewController *childController = [[ChildViewController alloc] initWithNibName:#"ChildView" bundle:nil];
self.childViewController = childController;
[childController release];
}
[self.mainViewControlle.view removeFromSuperView];
[self.view insertSubview:childViewController.view atIndex:0];
}
Hope this helps.
You might want to check out the Utility App sample -- it demonstrates switching between two views with animation and adding/removing views from parent views.
you might want to create a navigation controller in the main view and than push the childviewcontroller onto it when invoking showChildView. You'll get the back navigation button for free that way