If I have nested subviews, will all subviews get disposed if i call removefromsuperview?
Pseudocode:
UIView *viewA = [[UIView alloc] initWithFrame:CGRectMake(0 , 0, 100, 100)];
[self.view addSubview:viewA];
UIView *viewB = [[UIView alloc] initWithFrame:CGRectMake(25 , 25, 50, 50)];
[viewA addSubview:viewB];
UIButton *buttonC = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[viewB addSubview:buttonC];
And then buttonC is pressed:
[viewA removeFromSuperView];
All views are removed from the screen, but are they removed properly?
Do I need to remove all views manually?
All views will be removed. If you maintain a strong reference to viewA then all of the views will still be there and can be added again later. If you don't, they will all be destroyed.
As long as you have no other references to your views A..C, they will be removed and destroyed
You can check it easy. Create subclass of uiview, overide it dealloc method and set brakepoint there. Than create instance of this class and add it to your view as subview.
When you`ll call removeFromSuperview in your view brakepoint will be activated.
That`s it.
Related
I have three views : topView, middleView, bottomView.
When I clicked the button in the topView, I want to insert alpha view between topView and middleView.
but middleView and bottomView is already located by calling method [self.view addsubView:] at viewDidLoad.
So I have to change middleView and bottomView below the alpha view...
So I called method 'setFrame', but already added views didn't move to where i want to put them.
So I have to call method 'removeFromSuperView' but there is a big problem that middleView and bottomView are the master views that has multiple subviews into them...
I don't know how to solve this problem, please help me!
! middleView and bottomView, they just need to go down , moving issue is simple.
****UPDATE
My code about the issue is below :
authCodeView is alphaView
authCodeView = [[UIView alloc] initWithFrame:CGRectMake(0, topView.frame.size.height + 8, [UIScreen mainScreen].bounds.size.width, topView.frame.size.height)];
[authCodeView setBackgroundColor:[UIColor whiteColor]];
authCodeField = [[UITextField alloc] initWithFrame:CGRectMake(30, 0, authCodeView.frame.size.width - 30, authCodeView.frame.size.height)];
authCodeField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:#"인증번호 입력" attributes:#{NSForegroundColorAttributeName:tempGray}];
[authCodeView addSubview:authCodeField];
NSLog(#"%f",authCodeView.frame.origin.y+authCodeView.frame.size.height + 8);
[middleView setFrame:CGRectMake(100, authCodeView.frame.origin.y+authCodeView.frame.size.height + 8, [UIScreen mainScreen].bounds.size.width, 308.0f)];
[bottomView setFrame:CGRectMake(0, middleView.frame.origin.y+middleView.frame.size.height+8, [UIScreen mainScreen].bounds.size.width, bottomView.frame.size.height)];
[self.view addSubview:authCodeView];
[self.view addSubview:middleView];
[self.view addSubview:bottomView];
So I called method 'setFrame', but already added views didn't move to where i want to put them.
Then you passed the wrong rectangle to -setFrame:. That method changes the frame of the view, i.e. it's location and size in the coordinate system of its superview.
So I have to call method 'removeFromSuperView' but there is a big problem that middleView and bottomView are the master views that has multiple subviews
You don't need to remove a view just to change its position. You'd only need to remove it if you want to add it to some other view instead, or if you no longer want it in the superview at all. That said, it's not a problem if a view like middleView has subviews -- those will go along with middleView if you remove it from its superview, or if you change middleView's position, etc.
I don't know how to solve this problem, please help me!
When asking for help, you really need to post code that reproduces the problem you're trying to solve.
I want to add several ViewController's views as sub views of my another viewcontroller. So I have done like this inside my parent viewController.
-(void)MakeDisplayArea
{
vwDisplayArea=[[UIView alloc] initWithFrame:CGRectMake(0, 0, w, h-scrolTab.frame.size.height)];
[self.view addSubview:vwDisplayArea];
}
-(void)ProfClick :(id)sender
{
[self MakeDisplayArea];
ProfileViewController *profviewcontroller=[[ProfileViewController alloc] initWithNibName:#"ProfileViewController" bundle:nil];
profviewcontroller.view.frame=vwDisplayArea.frame;
[profviewcontroller.view setBackgroundColor:[UIColor clearColor]];
[vwDisplayArea addSubview:profviewcontroller.view];
}
Then inside the profViewcontroller ViewDidLoad methods I am generating a button and set the target like this.
UIButton *btn=[[UIButton alloc] initWithFrame:CGRectMake(10, 60, 100, 30)];
[btn setTitle:#"Button Test" forState:UIControlStateNormal];
[self.view addSubview:btn];
[btn addTarget:self action:#selector(btnClick:) forControlEvents:UIControlEventTouchUpInside];
-(IBAction)btnClick :(id)sender
{
NSLog(#"button clicked-------");
}
I can see the button is appearing on that profViewcontroller that I loaded as a sub view, but when I click the button the app is crashing. What is the correct way add that viewcontroller as a subview on my first viewcontroller. Please help me.
Thanks
Like maddy said you need child view controllers to add working subviews.
Look here: Creating Custom Container View Controllers
But working with them is not easy. Ask yourself if you really need to implement it. For the most cases you don't need it.
I have a simple xib file which its layout is:
Which the pale green UIView is referenced to an IBOutlet view_content in my UIViewController class. Then I did the following in initWithNibName:bundle: of my ViewController.m:
self = [super initWithNibName:nibNameOrNil bundle:nil];
if (self) {
self.view_a = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
self.view_a.backgroundColor = [UIColor purpleColor];
[self.view_content addSubview:self.view_a];
self.view_b = [[UIView alloc] initWithFrame:CGRectMake(150, 150, 100, 100)];
self.view_b.backgroundColor = [UIColor blueColor];
[self.view_content addSubview:self.view_b];
self.view_c = [[UIView alloc] initWithFrame:CGRectMake(200, 200, 100, 100)];
self.view_c.backgroundColor = [UIColor greenColor];
[self.view_content addSubview:self.view_c];
}
return self;
I expected there will be 3 small squares, each with different colors as declared in the code above, but they did not show up which the view is loaded and showed. But instead if I move the addSubView: calls into viewDidLoad, they are displayed as expected. I tried to test if view_content is nil in the if-segment and seems it is nil at that time. I don't understands why this is happening and how it works, isn't the view and its components are supposed to be loaded from the xib?
Thanks for any help!
At the point initWithNibName:... is called, the view itself is not yet loaded. This is an optimization (lazy loading) that defers loading the view until it is actually needed. The view is actually loaded when viewController.view is first-time accessed, and that's when viewDidLoad is called.
Some people force the view controler to load its view by calling [viewController view] (or [self view] if it's within the view controller's class).
The reason is simple. View is not loaded at that time when you are initializing the controller means initWithNibName. So best place is viewDidLoad where your all outlet has been assigned.
I can't see any of the view objects I've added programmatically. I need to link them to IBAction and/or IBOutlet, but without being able to ctrl-click-drag, I can't.
For example, I have this in viewDidLoad:
imageView = [[UIImageView alloc] initWithFrame:CGRectMake(789, 60, 215, 72)];
[imageView setAnimationImages:imgListArray];
[self.view addSubview:imageView];
The animation shows up in the simulator, but not in the storyboard.
How can I either make these objects show up in storyboard (preferred), or link them to IBActions/Outlets programmatically?
As #vikingsegundo said, Image Builder allows you to add objects to views and then connect them to IBOutlets and IBActions in your classes, but if you add things programatically then you are on your own in terms of Image Builder/Storyboards.
You can still create an iVar or property (preferred) to store the reference to your object, but you don't need the IBOutlet tag, so
#property (strong,nonatomic) UIImageView *imageView;
and then
self.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(789, 60, 215, 72)];
[self.imageView setAnimationImages:imgListArray];
[self.view addSubview:self.imageView];
You can also add action handlers to objects through code (the equivalent of ctrl-dragging to an IBAction method)
[self.aButton addTarget:self action:#selector(buttonEventHandler) forControlEvents: UIControlEventTouchUpInside];
To set a code-instantiated object as an instance variable, just set it. Like this:
// your code
imageView = [[UIImageView alloc] initWithFrame:CGRectMake(789, 60, 215, 72)];
[imageView setAnimationImages:imgListArray];
[self.view addSubview:imageView];
// and then:
self.myImageView = imageView; // assumes you've got a `#property` called `myImageView`
That's exactly the same thing that constructing an outlet connection in the storyboard does, but now you're doing it yourself.
To set a code-instantiated control's action, call addTarget:action:forControlEvents:.
That's exactly the same thing that setting up an action connection in the storyboard does, but now you're doing it yourself.
I want to change the existing view in a UIViewController to a new view. The new view contains the old view and a little banner view.
Doing this fairly simple change leaves me with a black view.
My code looks like this
UIView *existingView = self.view;
UIView *newView = [[UIView alloc] initWithFrame:existingView.frame];
UIView *bannerView = [[UIView alloc] initWithFrame:CGRectMake(0, (self.view.frame.size.height - 50), 320, 50)];
CGRect existingViewFrame = existingView.frame;
existingViewFrame.size.height -= 50;
existingView.frame = existingViewFrame;
[newView addSubview:existingView];
[newView addSubview:bannerView];
self.view = newView;
However when switch Tabs and come back to the view which changed the view is shown just like I want. I guess I need to set a flag or something to tell the controller to redraw it's (new) view.
Edit
I wrote an simple example for this problem. You can find it on GitHub: https://github.com/Oemera/ChangeView
You did not say where you do this. It may be that you need to save the original view's super view, then add the new view to that views subViews array. I'm betting that is the problem.