Advertise here




Advertise here

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Removing all subviews from a view

fladnagfladnag Posts: 93Registered Users
edited August 2011 in iOS SDK Development
Is there a way to remove all of a view's subviews instead of removing them individually by name like in the code below?
[myView1 removeFromSuperview];
Post edited by fladnag on
· ·

Replies

  • RickMaddyRickMaddy Posts: 2,122New Users
    edited October 2008
    What about:
    for (UIView *view in self.subviews) {
        [view removeFromSuperview];
    }
    
    · ·
  • fladnagfladnag Posts: 93Registered Users
    edited October 2008
    That worked perfectly. Thank you.
    · ·
  • jshake11jshake11 Posts: 14Registered Users
    edited October 2009
    for (UIView *view in self.subviews) {
        [view removeFromSuperview];
    }
    

    The above gave me the Warning message of "UIView may not respond to -countByEnumerationWithState:objects:count: And my code crashed when I tried to run it.

    I used this and it worked for me:
    // Assuming *view is already set up as a UIView...
    
    for (int i = 0; i < [[self.view subviews] count]; i++ ) {
        [[[self.view subviews] objectAtIndex:i] removeFromSuperview];
    }
    
    · ·
  • panzeritipanzeriti United StatesPosts: 757Registered Users @ @ @
    edited December 2009
    Neither of these worked for me.

    This would not compile for me:
    for (UIView *view in self.subviews) {
        [view removeFromSuperview];
    }
    

    And this did not remove all subviews for some reason:
    for (int i = 0; i < [[self.view subviews] count]; i++ ) {
        [[[self.view subviews] objectAtIndex:i] removeFromSuperview];
    }
    

    But what did work is as follows:
    for (UIView *view in [self.view subviews]) {
        [view removeFromSuperview];
    }
    

    This method compiled and removed all subviews.
    · ·
  • BrianSlickBrianSlick Treadmill Desk Ninja Posts: 10,568Tutorial Authors, Registered Users @ @ @ @ @ @ @ @
    edited December 2009
    The first one failed because subviews is not a property of self, which is presumably your view controller. If this was a custom UIView subclass, it would probably work.

    The second failed because it isn't approaching the problem correctly. If you are making the array smaller each time, you have to work backwards. If you remove the object at index 0, then the object that was at index 1 is now at index 0. But your next pass removes the object at index 1, and so on.

    I'm a little surprised that the 3rd one worked, because you can't change the size of the array when doing fast enumeration. I'm going to guess that it works here because the subviews property returns a copy of the array, so you aren't messing with the actual subview array.

    Somebody posted a cool array trick here a few weeks ago. I haven't tested this code, but it should be something like this:
    [[[self view] subviews] makeObjectsPerformSelector: @selector(removeFromSuperview)];
    
    BriTer Ideas LLC - WWW | Facebook | Twitter | LinkedIn - Professional iOS App Development. Available for hire.

    SlickShopper 2 | Leave a PayPal donation

    Free Xcode Tools: NSLog Utility | Getter Utility
    GitHub Projects: BTIKit | BTICoreDataKit

    Are you a newbie? Things you should read:
    Definitive Guide To Properties | UITableView Series | A Model (Object) Is A Beautiful Thing
    · ·
  • DenVogDenVog Posts: 625Registered Users
    edited March 2010
    panzeriti wrote: »
    Neither of these worked for me.

    But what did work is as follows:
    for (UIView *view in [self.view subviews]) {
        [view removeFromSuperview];
    }
    

    This method compiled and removed all subviews.

    Thanks for sharing this. I ran into the same issue. Your post save me a lot of time.
    · ·
  • mndhkrmndhkr Posts: 1New Users
    edited February 2011
    while([view.subviews count] > 0)
       [[view.subviews lastObject] removeFromSuperview];
    

    i think that a for cycle may cause some problem with the array varying in count while removing the subviews...
    · ·
  • TUX2KTUX2K Posts: 782Registered Users
    edited February 2011
    mndhkr wrote: »
    while([view.subviews count] > 0)
       [[view.subviews lastObject] removeFromSuperview];
    

    i think that a for cycle may cause some problem with the array varying in count while removing the subviews...
    And thats what BrianSlick said.
    If my answer helped you, you might want to help me.<br />
    Make a<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=YMPPFH4FX7Z6C" target="_blank"> donation via PayPal</a>.
    · ·
  • mariano_donatimariano_donati Posts: 345Registered Users @ @
    edited February 2011
    Just to add another way:
    for (int i = 0; i < [[self.view subviews] count]; i++ ) {
        [[[self.view subviews] objectAtIndex:0] removeFromSuperview];
    }
    
    <a href="http://www.thisissudoku.com" target="_blank">This Is Sudoku, a logic-based sudoku game</a>
    · ·
  • DAWDAW Posts: 3New Users
    edited April 2011
    Verbose but easy to follow...
    // Clear up existing scale if we need to by removing any labels
        int i,j;
        int totalSubViews = [[self.view subviews] count];
        for (i=0,j=0; i < totalSubViews; i++ ) 
        {
            if ([[[self.view subviews] objectAtIndex:j] isKindOfClass:[UILabel class]])
            {
                UILabel *thisLabel = [[self.view subviews] objectAtIndex:j];
                NSLog (@"Removing %@",thisLabel.text);
                [thisLabel removeFromSuperview];
            }
            else
                j++;
        }
    
    · ·
  • qdvictoryqdvictory Posts: 1New Users
    edited April 2011
    BrianSlick wrote: »
    The first one failed because subviews is not a property of self, which is presumably your view controller. If this was a custom UIView subclass, it would probably work.

    The second failed because it isn't approaching the problem correctly. If you are making the array smaller each time, you have to work backwards. If you remove the object at index 0, then the object that was at index 1 is now at index 0. But your next pass removes the object at index 1, and so on.

    I'm a little surprised that the 3rd one worked, because you can't change the size of the array when doing fast enumeration. I'm going to guess that it works here because the subviews property returns a copy of the array, so you aren't messing with the actual subview array.

    Somebody posted a cool array trick here a few weeks ago. I haven't tested this code, but it should be something like this:
    [[[self view] subviews] makeObjectsPerformSelector: @selector(removeFromSuperview)];
    

    this is a good way.
    · ·
  • pygmybutcherpygmybutcher Posts: 3New Users
    edited July 2011
    BrianSlick wrote: »

    Somebody posted a cool array trick here a few weeks ago. I haven't tested this code, but it should be something like this:
    [[[self view] subviews] makeObjectsPerformSelector: @selector(removeFromSuperview)];
    

    This is the most elegant of the methods posted here. Thanks, Brian.
    · ·
  • dany_devdany_dev Posts: 4,696Tutorial Authors, Registered Users @ @ @ @ @
    edited July 2011
    really I prefer
    for (UIView *view in [self.view subviews]) {
        [view removeFromSuperview];
    }
    

    :D
    · ·
  • CBGrahamCBGraham Posts: 18Registered Users
    edited July 2011
    This is the most elegant of the methods posted here. Thanks, Brian.

    Elegant is a dirty word. makeObjectsPerformSelector says in the docs that you shouldn't give it something that modifies the array. removeFromSuperview does. Make a copy of the subviews array and work on it and stop trying to write one line solutions. (Same problem as a vanilla For loop affecting the array it is working over.)
    · ·
  • BrianSlickBrianSlick Treadmill Desk Ninja Posts: 10,568Tutorial Authors, Registered Users @ @ @ @ @ @ @ @
    edited July 2011
    CBGraham wrote: »
    Elegant is a dirty word. makeObjectsPerformSelector says in the docs that you shouldn't give it something that modifies the array. removeFromSuperview does. Make a copy of the subviews array and work on it and stop trying to write one line solutions. (Same problem as a vanilla For loop affecting the array it is working over.)

    If you had actually read the documentation before posting, then you would know that this is unnecessary, since subviews is a copy property. Plus it is an NSArray, not an NSMutableArray, therefore it cannot be modified. So if this solution didn't work, it would crash very quickly, and this would have been noted here in this thread quite some time ago.
    BriTer Ideas LLC - WWW | Facebook | Twitter | LinkedIn - Professional iOS App Development. Available for hire.

    SlickShopper 2 | Leave a PayPal donation

    Free Xcode Tools: NSLog Utility | Getter Utility
    GitHub Projects: BTIKit | BTICoreDataKit

    Are you a newbie? Things you should read:
    Definitive Guide To Properties | UITableView Series | A Model (Object) Is A Beautiful Thing
    · ·
  • sneakysneaky Posts: 354Registered Users @ @
    edited August 2011
    What about when I have views within views?
    Will
    for (UIView *view in [self.view subviews]) {
    	[view removeFromSuperview];
    }
    
    remove all subviews of subviews or will I have to nest another for loop to get rid of them safely?
    · ·
  • BrianSlickBrianSlick Treadmill Desk Ninja Posts: 10,568Tutorial Authors, Registered Users @ @ @ @ @ @ @ @
    edited August 2011
    Perform experiments and find out.
    BriTer Ideas LLC - WWW | Facebook | Twitter | LinkedIn - Professional iOS App Development. Available for hire.

    SlickShopper 2 | Leave a PayPal donation

    Free Xcode Tools: NSLog Utility | Getter Utility
    GitHub Projects: BTIKit | BTICoreDataKit

    Are you a newbie? Things you should read:
    Definitive Guide To Properties | UITableView Series | A Model (Object) Is A Beautiful Thing
    · ·
  • sneakysneaky Posts: 354Registered Users @ @
    edited August 2011
    BrianSlick wrote: »
    Perform experiments and find out.

    That would make way too much sense, can't be doing that now! :D

    So I set up a button to place a view as a subview to self.view. On this subview I put a button that calls the remove from superview for loop.

    If the loop would not remove subviews of subviews I should see a leak in instruments but I was presenting and removing the view a good few times and no leak appeared so I think we can safely say that everything is indeed removed.
    · ·
Sign In or Register to comment.