Current location: Brighton, UK

Removing all subviews - a comparison of Objective-C vs ActionScript

Posted on , March 07, 2010 @ 20:48 CET

In Cocoa Touch a UIView object is similar to a DisplayObject in ActionScript. You can add a child to its "display list" by saying:

[myMainView addSubview:myOtherView];

To remove the view you say:

[myOtherView removeFromSuperview];

As far as I can tell there is no removeChild like we're used to in AS.

But what if you want to remove all of the children or subviews? Well, we're not as lucky as containers in Flex with that snazzy removeAllChildren() method, but we can loop through the list and tell each subview to remove itself like we do in plain-ol' ActionScript:

while(myMainView.children) {
myMainView.removeChildAt(0);
}

In Objective-C this would be:

while([[myMainView subviews] count]) {
[[[myMainView subviews] objectAtIndex:0] removeFromSuperview];
}

And this works fine. But today I learned a pretty cool trick. Basically [myMainView subviews] is an array just like myMainView.children. And NSArray has this cool method called makeObjectsPerformSelector which basically means make every object in the array call whatever method you want them to.

So instead of looping through you can simply say the following:

[[myMainView subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];

How cool is that! Not exactly a [myMainView removeAllSubviews] but still :)

- paulo

Comments:

1
Keith Peters writes:
Neat trick. Will try to remember that one.

# March 07, 2010 21:00 CET

2
Mats Karstad writes:
Cool! :) Personally I could not understand why there was no removeAll function.

# March 07, 2010 21:24 CET

3
Paulo Fierro replies:
@Mats: yeah, when I'm playing with Cocoa and come across something that doesn't feel quite right I normally imagine that I'm just doing something wrong and there's a better way to do it. But in this case I haven't found anything easier than this :)

# March 08, 2010 14:14 CET

4
j writes:
Actually, according to the docs you should not use the makeObjectsPerformSselector if the selector modifies the array:
aSelector

A selector that identifies the message to send to the objects in the receiver. The method must not take any arguments, and must not have the side effect of modifying the receiving array.

Hence I would not recommend using this method to remove all subviews.
Some people suggest

for (UIView *v in [myMainView subviews]) {
[v removeFromSuperview];
}

Again, I'm not sure if you're allowed to modify the array while you're iterating through it.
I'd suggest

while([[myMainView subviews] count]) {
[[[myMainView subviews] lastObject] removeFromSuperview];
}

So I would remove the last object and not the first one to avoid having to shift all succeeding array elements.

# March 29, 2010 12:48 CET

5
j writes:
Actually, I have to correct myself. UIView.subviews returns a copy of the view's subview array, so it's fine to use the makeObjectsPerformSelector method on the copy since the removeFromeSuperview will not affect the copy but the actual subviews array.

# March 29, 2010 12:58 CET

Post a comment:

You must have Flash and JavaScript enabled to post a comment.