in my application two views are there, their names are Loginview and sampleview
this Loginview i added to [self.view addsubview:Loginview];
after login action. i changed self.view as [self.view addsubview:sampleview];
but that time also loginview is showing..
to avoid this. how to remove sub view in self.view?
This will remove all the subviews:
for (UIView *view in self.view.subviews)
{
[view removeFromSuperView];
}
Related
I'm writing an app with a tabbarcontroller that holds some NavigationViewController. Each of This NavigationController holds some ViewControllers. Sometimes during navigation i need to hide the tabbar, the code i use:
- (void) hideTabBar:(UITabBarController *) tabbarcontroller {
for(UIView *view in tabbarcontroller.view.subviews)
{
if([view isKindOfClass:[UITabBar class]])
{
[view setFrame:CGRectMake(view.frame.origin.x, [self ScreenHeight], view.frame.size.width, view.frame.size.height)];
}
else
{
[view setFrame:CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, [self ScreenHeight])];
}
}
}
All works great until i try to add a button at the bottom of the screen. I can't touch a button placed in the bottom of the screen, tabbar is correctly hidden and the button is visible... If i move up the button it returns to works correctly...It seems like the tabbar never moves out of the screen... How i can do?
try this
ViewController* vC = [[ViewController alloc] init];
vC.hidesBottomBarWhenPushed = YES;
and make sure that button is at uppermost level. in your case bottom toolbar hiding button
i had done it with your code and it works perfect for me
download project
Description
Tab bar is hidden using code given by OP and
Screen
I've been struggling with a bug, and I found a work-around, but I'd like to understand what is exactly going on. it has something to do with UIButton target actions misfiring depending on different subview hierarchies, inside a subclass.
Brief summary: I have a subclass of NSObject with a UIView property object, a UIButton attached to it, and a target added to the button calling a function inside the subclass. Inside the main ViewController, I init the subclass and add its view to the view stack, click the button, and it throws me to main.mm with the error - EXC_BAD_ACCESS, gives me little feedback. so the hierarchy looks like this:
-CustomClass
--UIView <-this is added as a subview to the View Controller
---UIButton (onRelease calling a function)
so I fixed it by changing the custom class to be a subclass of UIView instead of NSObject, then add its #property UIView to be a subview of the custom class (and the button is still attached to the subview), and then in the main View Controller, I add the custom class itself as a subview, not the class's subview property object. then the button successfully calls the function. so the new arrangement looks like this:
-CustomClass (now UIView) <-this is added as a subview to the View Controller
--UIView <-this is added as a subview to CustomClass
---UIButton (onRelease calling a function)
then, i realized i can just keep the CustomClass a subclass of UIView for both instances, the problem persists with the original setup if everything else is unchanged.
okay, more detail, here's code:
CustomClass:
.h
#interface Temp : UIView
#property UIView *subview;
#property UIButton *but;
#end
.m
-(id) init{
self = [super initWithFrame:[[UIScreen mainScreen] bounds]];
if(self){
_subview = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
//[self addSubview:_subview]; // FOR THE FIX
_but = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[_but setTitle:#"OKAY" forState:UIControlStateNormal];
[_but setBackgroundColor:[UIColor blackColor]];
[_but setFrame:CGRectMake(50, 50, 200, 200)];
[_subview addSubview:_but];
[_but addTarget:self action:#selector(pageTurn) forControlEvents:UIControlEventTouchUpInside];
}
return self;
}
-(void) pageTurn{
NSLog(#"WORKS");
}
inside view controller:
Temp *temp = [[Temp alloc] init];
[self.view addSubview:temp.subview];
//[self.view addSubview:temp]; // FOR THE FIX, instead of above line
Who's holding onto temp?
If temp isn't referenced by anyone then it's released. At that point the target is zombie and of course you will crash. temp.subview is being held by self.view.
In the second setup, adding temp as a subview of self.view keeps a reference to it.
You can fix this by adding a Temp * property in the view controller.
self.temp = [[Temp alloc] init];
[self.view addSubview:self.temp.subview];
You're messing with all kinds of view hierarchy stuff you don't need to, which is likely the cause of the problem. I created a Test UIView subclass that had a UIButton instance variable that I added as a subview in the Test object, there's no need to add another view as a subview and then add the button to the subview, and then in your view controller add the button's subview to the view - it's WAY more complicated than it needs to be.
In a nutshell - Create the Temp UIView, add the button as a subview, then in your view controller class add the Temp UIView as a subview. Simple as that, here is the code:
- (id)init {
self = [super initWithFrame:[[UIScreen mainScreen] bounds]];
if(self){
_but = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[_but setTitle:#"OKAY" forState:UIControlStateNormal];
[_but setBackgroundColor:[UIColor blackColor]];
[_but setFrame:CGRectMake(100, 100, 200, 200)];
[_but addTarget:self action:#selector(pageTurn) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:_but];
}
return self;
}
- (void)pageTurn {
NSLog(#"WORKS");
}
Then added an instance to my view controller:
Test *temp = [[Test alloc] init];
temp.backgroundColor = [UIColor redColor];
[self.view addSubview:temp];
This was the result:
The scrollview in my main page stop working if I push something to the navigation controller and then pop back to the main page. It works normally if I reopen the application without pushing anything to the navigation controller yet. The scrollview is a horizontal scrollview which extends beyond the frame. I use it to scroll through buttons like when you switch application in iOS (iOS multitasking).
This is the code where I push a new vc
UIViewController *newVC = [[UIViewController alloc] init];
UILabel *label = [[UILabel alloc] initWithFrame:self.view.bounds];
[label setTextAlignment:NSTextAlignmentCenter];
label.text = [NSString stringWithFormat:#"promo %i detail view",[sender tag]];
label.backgroundColor = [UIColor whiteColor];
[newVC.view addSubview:label];
[self.navigationController setNavigationBarHidden:NO animated:NO];
[self.navigationController pushViewController:newVC animated:YES];
when that view controller is popped and navigation controller move back to the main page I hide the navigationBar.
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
if(viewController == self){
[self.navigationController setNavigationBarHidden:YES];
NSLog(#"%d", [self.scrollMenuBar isScrollEnabled]);
}
}
checking isScrollEnable return true.
I tried pushing a normal modal view and the same problem occur.
If you resize the scroll view content size in the viewDidLayoutSubview function it will work again.
- (void) viewDidLayoutSubviews {
[self resizeScrollViewContent];
}
Add
[self.scrollbarMenu setScrollEnabled:YES]; in viewdidAppear of main page
Add
[scroll setContentSize:CGSizeMake(width , height)];
Still if it doesnt work
2 possibilities
Memory is not valid.
Some other view comes above the scrollview
Problem solved by creating the UIScrollview and the button inside it programmatically. Not sure what I did wrong with storyboard, but it's a pain.
UIViewController *viewController = [[UIViewController alloc] init];
UIView *view1 = [[UIView alloc] init];
[viewController.view addSubview:view1];
[view1 release];
if I want release viewController;
[viewController release];
do I need manual release view1 before release viewController?
UIView *view = (UIView *)[[viewController.view subviews] objectAtIndex:0];
[view release];
[viewController release];
should I do this? or just release viewController?
No, you dont have to do that. Just release viewController and it will release all of its subviews internally. Rest will be taken care by framework.
If you are not using ARC, your code will look like this,
UIViewController *viewController = [[UIViewController alloc] init];
UIView *view1 = [[UIView alloc] init];
[viewController.view addSubview:view1];
[view1 release];
[viewController release];
Since you have allocated both viewController and view1 once, you have to release it once as shown above. You dont have to do a release again since you are not doing any retain on this after that.
If you do this,
UIView *view = (UIView *)[[viewController.view subviews] objectAtIndex:0];
[view release];
It will mostly result in a crash when viewController is released since you are releasing it twice and viewController's subviews are also getting released internally.
Here once thing you have to note is that, addSubview retains view1 as mentioned in Apple documentation.
The view to be added. This view is retained by the receiver.
After being added, this view appears on top of any other subviews.
This will be released once viewController is released and you dont have to manually release it since you dont own it.
This is the correct way.
UIViewController *viewController = [[UIViewController alloc] init];
UIView *view1 = [[UIView alloc] init];
[viewController.view addSubview:view1];
[view1 release];
[viewController release];
When you add a view as subview it'll be retained by the viewcontroller.
addSubview:
Adds a view to the end of the receiver’s list of subviews.
- (void)addSubview:(UIView *)view
Parameters
view
The view to be added. This view is retained by the receiver. After being added, this view appears on top of any other subviews.
Discussion
This method retains view and sets its next responder to the receiver,
which is its new superview.
Views can have only one superview. If view already has a superview and
that view is not the receiver, this method removes the previous
superview before making the receiver its new superview.
Reference UIView
Important: A view controller is the sole owner of its view and any
subviews it creates. It is responsible for creating those views and
for relinquishing ownership of them at the appropriate times such as
when the view controller itself is released
Reference : UIViewController Class
UIView *view = (UIView *)[[viewController.view subviews] objectAtIndex:0];
[view release];
It'll surely crash when you call release on viewController.
I have an UINavigationController which the user navigates with.
When pushing a specific UIViewController onto the navigation stack, a "settings" button appear in the navigationBar. When the user clicks this button I would like to flip the current view/controller, i.e. everything on screen, including the navigationBar, over to a settings view.
So I have a SettingsViewController which I would like to flip to from my CurrentViewController that lives on a navigationController stack.
I get all kinds of strange behavior trying to do this, the UIViews belonging to the SettingsViewController will start to animate, sliding into place, the navigationButtons moves around, nothing acts as I would think.
-(void)settingsHandler {
SettingViewController *settingsView = [[SettingViewController alloc] init];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight
forView:self.navigationController.view
cache:YES];
[self.navigationController.view addSubview:settingsView.view];
[UIView commitAnimations];
}
The above results in the views flipping correctly, but the subviews of the SettingsViewController are all positioned in (0, 0) and after the transition, they 'snap' into place?
Is it because I instantiate and add my subviews in viewDidLoad, like this?
- (void)viewDidLoad {
UIImageView *imageBg = [[UIImageView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 320.0f, 460.0f)];
[imageBg setImage:[UIImage imageNamed:#"background.png"]];
[self.view addSubview:imageBg];
[imageBg release];
SettingsSubview *switchView = [[SettingsSubview alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 320.0f, 460.0f)];
[self.view addSubview:switchView];
[switchView release];
[super viewDidLoad];
}
1: How should I correctly do the "flip" transition, from within the UIViewController in the UINavigationController, to a new UIViewController and subsequently from the new UIViewController and back to the "original" UIViewController residing on the UINavigationControllers stack?
2: Should I use a different approach, than the "viewDidLoad" method, when instantiating and adding subviews to a UIViewController?
-question 2 is more of a "best practice" thing. I have seen different ways
of doing it and I am having trouble either finding or understanding the life-cycle documentation and the different threads and posts on the subject. I am missing the "best practice" examples.
Thank You very much for any help given:)
If you want to create your view hierarchy programmatically, the place to do it is in -loadView. To do so you must create the view yourself, add all of its subviews, and then assign it to the view property, like this:
- (void)loadView {
UIView *containerView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 320.0f, 460.0f)];
UIImageView *imageBg = [[UIImageView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 320.0f, 460.0f)];
[imageBg setImage:[UIImage imageNamed:#"background.png"]];
[containerView addSubview:imageBg];
[imageBg release];
SettingsSubview *switchView = [[SettingsSubview alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 320.0f, 460.0f)];
[containerView addSubview:switchView];
[switchView release];
self.view = containerView;
[containerView release];
}
It helps to understand the context in which this method gets called, and how it behaves by default. The first time the view property of a UIViewController is accessed, the default getter method calls -loadView to lazy-load the view. The default implementation of -loadView loads the view from a nib if one was specified. Otherwise it creates a plain UIView object and sets that as the controller's view. By overriding this method, you can ensure that your view's hierarchy will be fully formed the first time it is accessed.
-viewDidLoad should be used for any subsequent setup that needs to occur after the view hierarchy is fully loaded. This method will get called whether the view is loaded from a nib or constructed programmatically in loadView.