Reputation: 28720
how do i remove all subviews from my scrollview...
i have a uiview and a button above it in the scrollview something like this....
here is my code to add subview in scroll view
-(void)AddOneButton:(NSInteger)myButtonTag {
lastButtonNumber = lastButtonNumber + 1;
if ((lastButtonNumber == 1) || ((lastButtonNumber%2) == 1)) {
btnLeft = 8;}
else if ((lastButtonNumber == 2) || ((lastButtonNumber%2) == 0)) {
btnLeft = 162;
}
CGRect frame1 = CGRectMake(btnLeft, btnTop, 150, 150);
CGRect frame2 = CGRectMake(btnLeft, btnTop, 150, 150);
UIButton *Button = [UIButton buttonWithType:UIButtonTypeCustom];
Button.frame = frame1;
Button.tag = myButtonTag;
[Button addTarget:self action:@selector(buttonClick:) forControlEvents:UIControlEventTouchUpInside];
[Button setBackgroundColor:[UIColor clearColor]];
[Button setBackgroundImage:[UIImage imageNamed:@"WaitScreen.png"] forState:UIControlStateHighlighted];
GraphThumbViewControllerobj = [[GraphThumbViewController alloc] initWithPageNumber:[[GraphIdArray objectAtIndex:myButtonTag]intValue]];
GraphThumbViewControllerobj.view.frame=frame2;
GraphThumbViewControllerobj.lblCounter.text=[NSString stringWithFormat:@"%d of %d",myButtonTag+1,flashCardsId.count];
GraphThumbViewControllerobj.lblQuestion.text=[flashCardText objectAtIndex:myButtonTag];
[myScrollView addSubview:GraphThumbViewControllerobj.view];
[myScrollView addSubview:Button];
if ((lastButtonNumber == 2) || ((lastButtonNumber%2) == 0)) {
btnTop = btnTop + 162;
}
if (btnTop+150 > myScrollView.frame.size.height) {
myScrollView.contentSize = CGSizeMake((myScrollView.frame.size.width), (btnTop+160));}
}
and here is the code to remove subviews
if(myScrollView!=nil)
{
while ([myScrollView.subviews count] > 0) {
//NSLog(@"subviews Count=%d",[[myScrollView subviews]count]);
[[[myScrollView subviews] objectAtIndex:0] removeFromSuperview];
}
Upvotes: 32
Views: 66072
Reputation: 4686
An old question; but as it's the first hit on Google for this I thought I'd also make a note that there's also this method:
[[myScrollView subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];
You can't do the isKindOfClass check with this, but it's still a good solution to know about.
Edit: Another point to note is that the scrollbar of a scrollview is added as a subview to that scrollview. Thus if you iterate through all the subviews of a scrollview you will come across it. If removed it'll add itself again - but it's important to know this if you're only expecting your own UIView subclasses to be in there.
Amendment for Swift 3:
myScrollView.subviews.forEach { $0.removeFromSuperview() }
Upvotes: 38
Reputation: 5249
for(subview) in self.scrollView.subviews {
subview.removeFromSuperview()
}
Upvotes: 0
Reputation: 1130
The best and easiest is to use
for(UIView *subview in [scrollView subviews])
{
[subview removeFromSuperview];
}
This indeed causes crash as the basic rule is array shouldn't modified while being enumerated, to prevent that we can use
[[scrollView subviews]
makeObjectsPerformSelector:@selector(removeFromSuperview)];
But sometimes crash is still appearing because makeObjectsPerformSelector: will enumerate and performs selector, Also in iOS 7 ui operations are optimized to perform more faster than in iOS 6, Hence the best way to iterate array reversely and remove
NSArray *vs=[scrollView subviews];
for(int i=vs.count-1;i>=0;i--)
{
[((UIView*)[vs objectAtIndex:i]) removeFromSuperview];
}
Note : enumerating harms modification but not iterating...
Upvotes: 1
Reputation: 1556
The easiest and Best way is
for(UIView *subview in [scrollView subviews]) {
[subview removeFromSuperview];
}
Upvotes: 0
Reputation: 973
The problem with the UIScrollView and others subclass of UIView is that they contains initially some views (like the vertical and horizontal scrollbar for the UIScrollView). So i created a category of UIView to delete the Subviews filtered on the class.
For example:
[UIScrollView removeAllSubviewsOfClass:[FooView class],[BarView class],nil];
The code:
- (void)removeAllSubviewsOfClass:(Class)firstClass, ... NS_REQUIRES_NIL_TERMINATION;
- (void)removeAllSubviewsOfClass:(Class)firstClass, ...
{
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"FALSEPREDICATE"];
va_list args;
va_start(args, firstClass);
for (Class class = firstClass; class != nil; class = va_arg(args, Class))
{
predicate = [NSCompoundPredicate orPredicateWithSubpredicates:[NSArray arrayWithObjects:predicate,[NSPredicate predicateWithFormat:@"self isKindOfClass:%@",class], nil]];
}
va_end(args);
[[self.subviews filteredArrayUsingPredicate:predicate] makeObjectsPerformSelector:@selector(removeFromSuperview)];
}
Upvotes: 2
Reputation: 793
I don't think you should use the fast enumeration suggestion.
for(UIView *subview in [view subviews]) {
[subview removeFromSuperview];
}
Isn't this supposed to throw an exception if you change the collection being iterated? http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocFastEnumeration.html#//apple_ref/doc/uid/TP30001163-CH18-SW3
This example may be better.
NSArray *subviews = [[scroller subviews] copy];
for (UIView *subview in subviews) {
[subview removeFromSuperview];
}
[subviews release];
Upvotes: 9
Reputation: 449
To add to what Tim said, I noticed that you are tagging your views. If you wanted to remove a view with a certain tag you could use:
[[myScrollView viewWithTag:myButtonTag] removeFromSuperview];
Upvotes: 9
Reputation: 60110
To remove all the subviews from any view, you can iterate over the subviews and send each a removeFromSuperview
call:
// With some valid UIView *view:
for(UIView *subview in [view subviews]) {
[subview removeFromSuperview];
}
This is entirely unconditional, though, and will get rid of all subviews in the given view. If you want something more fine-grained, you could take any of several different approaches:
removeFromSuperview
messages later in the same mannerremoveFromSuperview
individually as necessaryif
statement to the above loop, checking for class equality. For example, to only remove all the UIButtons (or custom subclasses of UIButton) that exist in a view, you could use something like:// Again, valid UIView *view:
for(UIView *subview in [view subviews]) {
if([subview isKindOfClass:[UIButton class]]) {
[subview removeFromSuperview];
} else {
// Do nothing - not a UIButton or subclass instance
}
}
Upvotes: 104