What is the difference between addSubview and insertSubView methods when a view is added programmatically?
The only difference is in where the view is added: whether it is the frontmost view (addSubview:), or it is before the 5th subview, (insertSubview:atIndex:) or if it is immediately behind another subview (insertSubview:aboveSubview:).
Using insertSubView: you can specify the index, which determines z-order of views. A view with a higher index lies above those with lower indices.
I don't think there is a difference. addSubview: is simple a convenient method for
[view insertSubview:aView atIndex:[view.subviews count]]
1.addSubview add subview in array then add in View'slayer
- (void)addSubview:(UIView *)subview
{
[_subviews addObject:subview];
[_layer addSublayer:subview.layer];
}
}
2.While insertSubview add your view as subview then call
[_layer insertSublayer:subview.layer atIndex:index];
- (void)insertSubview:(UIView *)subview atIndex:(NSInteger)index
{
[self addSubview:subview];
[_layer insertSublayer:subview.layer atIndex:index];
}
Related
I have UIView in my storyboard with outlet mynewView and i want it display with totally different content. And do it many times.
My UIView contains many objects, i load it from internet. But every time i do
NSArray *viewsToRemove = [view1 mynewView];
for (UIView *v in viewsToRemove) {
[v removeFromSuperview];
}
//Let's try to remove all possible views..
viewsToRemove = [self.view subviews];
for (UIView *v in viewsToRemove) {
[v removeFromSuperview];
}
//here i create mynewView
mynewView = [self createnewRandomView];
//And finally add the View we have created.
[self.view addSubview:mynewView];
i monitor the memory consumption and i see it grows every time i add new UIView. Even when i remove all superviews. I guess they remain in memory.
Before i change the view i remove from superview all possible views, but they still stay in memory.
Xcode is set to use ARC so i can't release it.
Is there any good way to reuse a UIView?
Thanks
[self.view addSubview:mynewView];
Your newView was added as subview of self.view.
Your above code does not use for remove yourVewView in self.view.
Please try this code before adding new view:
for (UIView *view in self.view) {
if([view isKindOfClass:[YourNewViewClassName class]])
{
[view removeFromSuperView];
break;
}
}
As you remove the subviews, set them to nil as you go, like so:
for (UIView *v in viewsToRemove) {
[v removeFromSuperview];
v = nil;
}
For more information, see for example Arc: Setting references to nil, for multiple buttons
I'm wanting to control the master volume of the iPhone with a UISlider. There is a way of doing it without code and I've forgot how to. So code or within the xib, how do I do this?
Thanks
You can try the following method:
Place it in your XIB.
Open the XIB where you want to place to slider into
Add a UIView to your view
Change the class identity from UIView to MPVolumeView
Change backgroundColor to clear
Assuming you already have an instance of the MPVolumeView class, you need to search its subviews to find the MPVolumeSlider view:
UISlider *volumeViewSlider;
// Find the MPVolumeSlider
for (UIView *view in [volumeView subviews])
{
if ([[[view class] description] isEqualToString:#"MPVolumeSlider"])
{
volumeViewSlider = view;
}
}
[volumeViewSlider setValue: 1.0f animated:YES];
[volumeViewSlider _commitVolumeChange];
Hope this helps you out.
In my program,I called subview from main superview with the following code: [self.viewaddSubview:mysubView.view]; I want to navigate from subview to previous superview like 'back function'.How can do like that? For My project,I use xCode 3.0.
You can use methods removeFromSuperview and bringSubviewToFront.
It sounds like what you really want is basic navigation bar functionality with a "back" button.
Check out UINavigationController and these two functions
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
and
- (UIViewController *)popViewControllerAnimated:(BOOL)animated
at this documentation page:
http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UINavigationController_Class/Reference/Reference.html
yes.You can,
sendSubviewToBack:
[self.view sendSubviewToBack:mysubView.view];
or
[mysubView.view removeFromSuperview];
You must get the object of subview in superView and store them into an array and than remove them according to there index position. If you use only single subview in super view than follow this code :
NSArray *arr = [SuperView subviews];
NSLog ("objects in arr %#",arr);
[[arr objectAtIndex:0] removeFromSuperview];
In a view based app, I display a view and once the user is finished with that view, Done is clicked and the view is removed. However, that does not dealloc the view, which is what I want to do. What is the proper way to dealloc this type of view?
Currently, I'm nil'ing out the second view before it is called. That seems to work and the second view is reinitialized. However, isn't it more appropriate for the second view to destroy itself (nil itself after removeFromSuperview)?
In first view:
//show next view
aView = nil;
if(aView == nil)
{
aView = [[AView alloc] initWithNibName:#"aView" bundle:nil];
}
[self.view addSubview: aView.view];
Click Done in aView
[self.view removeFromSuperview];
The method removeFromSuperview will automatically release "aView.view", so you shouldn't release aView in the first view controller. I think you've declared AView *aView in head file, but you don't need to. You may declare the aView as a local variable like this:
// go to second view
SecViewController *sec = [[SecViewController alloc] initWithNibName:#"SecView" bundle:nil];
[self.view addSubview:sec.view];
// go back
[self.view removeFromSuperview];
Immediately after
[self.view addSubview: aView.view];
You should add:
[aView release];
Your subview has been retained by your view controller's view so can be release.
If you previously set your viewController to first responder status (like to respond to motion events) the responder chain will retain the controller. You must resign the first responder to destroy the controller completely.
[self resignFirstResponder];
[self.view removeFromSuperview];
both of the above answers are correct theory for how you should memory manage in objective c.
as per the dev documentation:
http://developer.apple.com/iPhone/library/documentation/UIKit/Reference/UIView_Class/UIView/UIView.html#//apple_ref/occ/instm/UIView/removeFromSuperview
callling removeFromSuperview will actually call release FOR you, so you are okay, I think.
I'm using an tableView with custom cells. When I want to display another view using the pushViewController function of the navigationController I loop through the textfields and call resignFirstResponder on them. But resignFirstResponder does only work when the textfields are being displayed so I scroll first to the top of the page. This is the code:
NSIndexPath *topIndexPath;
topIndexPath = [[NSIndexPath indexPathWithIndex:0] indexPathByAddingIndex:0];
[self.tableView scrollToRowAtIndexPath:topIndexPath atScrollPosition:UITableViewScrollPositionTop animated:NO];
[[self textFieldForRow:0] resignFirstResponder];
[[self textFieldForRow:1] resignFirstResponder];
[[self textFieldForRow:2] resignFirstResponder];
[[self textFieldForRow:3] resignFirstResponder];
This works, but after this my tableView has some weird problem with its origin. I tried to set it's superviews origin to 0, but that doesn't help.
Here is a screenshot of the problem: link
As you can see, my tableview is too large and the scrollbar is stuck in the middle of the view when reaching the bottom.
Sorry for my english, I hope that you can understand me,
Thanks in advance!
Hans
It was actually quite simple. Just put your resignFirstResponder in -viewWillDisappear
edit: this is better and less hacky, I added this to my class, and it worked:
edit 2: seems that your app will be rejected when using the previous code. Here is a updated public api version:
- (void)viewWillDisappear:(BOOL)animated
{
[self.view findAndResignFirstResponder];
}
And:
#implementation UIView (FindAndResignFirstResponder)
- (BOOL)findAndResignFirstResponder
{
if (self.isFirstResponder) {
[self resignFirstResponder];
return YES;
}
for (UIView *subView in self.subviews) {
if ([subView findAndResignFirstResponder])
return YES;
}
return NO;
}
#end
(source: Get the current first responder without using a private API)
I would fix your other problem. I imagine when you say you can't call "resignFirstResponder" when the other textFields are on screen, you mean that there is a crash?
If so, it is because of screen cells don't exist and therefore the textfields are gone as well. They are recycled (so they can be dequeued for new cells).
The easy solution is to only call resignFirstResponder only on textFields that ARE on screen.
What you are doing now seems a little hacky.