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:
Neat trick. Will try to remember that one.
# March 07, 2010 21:00 CET
Cool! :) Personally I could not understand why there was no removeAll function.
# March 07, 2010 21:24 CET
@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
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
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.