I have a bunch of UIViews that I subclassed that I have been adding to self.view e.g.:
MySpecialView *myView = [[MySpecialView alloc] init];
[self.view addSubview:myView];
Now I want to remove them all from self.view but only those custom ones. I don't want to remove any of the others (I have some other views with options in them etc). Is there anyway of doing this at all? Can I loop through all the subviews and check their type? Any pointers on this would be great! Thanks!
Try a loop like this
for (UIView *view in self.view.subviews)
{
if ([view isKindOfClass:[MySpecialView class]])
[view removeFromSuperview];
}
This simply iterates through all of the subviews and removes any that are of class MySpecialView.
Swift way
for subview in self.view.subviews {
if subview.isKindOfClass(MyClass) {
// Is that class!
} else if subview.isMemberOfClass(MyClass) {
// Is that class or a subclass of that class!
}
}
Related
I am creating a UIView every time I click on the button, but the problem is all other views are not getting deleted.
It's increasing the memory of the application
You can set a tag for UIView objects.
UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
view.tag = 2016;
[self addSubview:view];
Then, you can remove it later using this code :
UIView *view = [self viewWithTag:2016];
[view removeFromSuperview];
You can also keep a reference to an UIView object with a property.
#property (nonatomic, strong) UIView *view;
So you can remove it very easy.
Try this:
Assign a tag(may be 100) to the button.
NSArray *subviews = self.view.subviews;
for(UIView *subview in subviews) {
if(subview.tag != 100) {
[view removeFromSuperview];
}
}
-removeFromSuperview method release's memory after it is called only in case if your view is not retained by anything else
e.g.
Simply removing view from superview may not be sufficient to deallocate it can have view that has an outlet connection & declared property for it with retain or strong attribute, so in this case it will be retained by the controller while it is being loaded from nib file and you may need to release that view.
[yourView removeFromSuperview];
self.yourView = nil;
So I have a UIScrollView that is populated with a series of MyCustomViews that are subclasses of a standard UIView. In the delegate callback "scrollViewDidScroll I am trying to loop through all the subviews and call a specific function on them but I don't think the typecasting is working. Here is my code below:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
for(UIView *subView in [scrollView subviews){
MyCustomView *customView = (MyCustomView *)subView;
[customView myMethod];
}
}
When I call "myMethod" on customView, the program crashes saying an unrecognized selector was sent to instance. I believe that my type-casting is the issue as the method myMethod works in other situations. So how do I remedy this situation?
Solution 1:
If you do the following, you don't even need to cast your object to MyCustomView *. It can be of any type, e.g. UIView.
if([subView respondsToSelector:#selector(myMethod)]) {
[subView performSelector:#selector(myMethod)];
}
Solution 2:
You can check the object type before doing the cast.
if([subView isKindOfClass:[MyCustomView class]]) {
MyCustomView *customView = (MyCustomView *)subView;
[customView myMethod];
}
For "catch" this issue, use
if([customView respondsToSelector:#selector(myMethod)]){
[customView myMethod];
}
and with this, the app don't crash.
Also in your for use for(MyCustomView* customView in [scrollView subviews]){
I add some UIViews to my view using following method:
[self.view addSubview:myStickerView]; // this line is called every time when I select a button from ScrollView.
So, I can have a lot of myStickerView on my self.view.
Now, when I call this line: [myStickerView removeFromSuperview]; it will remove only my last myStickerView.
How can I remove all UIViews (myStickerView)?
The easiest way would be something like this:
for (UIView *view in self.view.subviews) {
if ([view isKindOfClass:[MYStickerView class]) {
[view removeFromSuperView];
}
}
Or you can store references for all inserted sticker views not to go through every subview
The easiest way would be to have an NSMutableArray property that kept track of your sticker views. When you add a sticker view to your view, add it to the array as well, that way you could do something like this when you wanted to remove all the sticker views
-(void)removeStickerViews
{
for(StickerView *stickerView in self.myStickerViewArray)
{
[stickerView doSomething];
[stickerView removeFromSuperview];
}
[self.myStickerViewArray removeAllObjects];
}
-(void)addStickerView:(StickerView *)inStickerView
{
[self.myStickerViewArray addObject:inStickerView];
[self.view addSubview:inStickerView];
}
The idea of keeping track in an array is fine, but I suggest using the more elegant [myArray makeObjectsPerformSelector:#selector(removeFromSuperview)] to achieve the result.
In my app I need to call some UIViews more than once. But in one of my method, i've a code like :
[self addSubview:UIImageView];
But i've read that addsubview method must be call once. So, to let the code how is it, how could I check if it's already on subview ? Like :
if ([UIImageView isOnSubview] == NO)
{
[self addSubview:UIImageView];
}
Because I don't find any method to check this :/
Thank you !
You are probably looking for UIView's -(BOOL)isDescendantOfView:(UIView *)view; taken in UIView class reference.
use this one
for (UIView *subview in [self subviews])
{
NSLog(#"%#", subview);
// ---------- remember one thing there should be one imageview ------
if(![subview isKindOfClass:[UIImageView class]])
{
[self addSubview:UIImageView];
}
}
I want to check if my view has already been added to the view, so that the user cannot repeatedly add the new UIViewController onto the view.
if (!self.fmovc)
{
self.fmovc = [[FMOVC alloc] initWithNibName: #"FMOVC" bundle:nil];
}
BOOL viewAlreadyDisplayed = NO;
for (UIView * b in self.view.subviews)
{
if ([b isKindOfClass:[FMOVC class]])
{
viewAlreadyDisplayed = YES;
}
}
if (!viewAlreadyDisplayed)
{
[self.view addSubview:self.fmovc.view];
}
This is not working because it never triggers
viewAlreadyDisplayed = YES;
What is the correct way to go about finding if your view is already being displayed?
Thanks,
-Code
Before adding just removeItFromSuperView...It may solve your prob
[self.fmovc.view removeFromSuperview];
[self.view addSubview:self.fmovc.view];
Make the UIView member variable say thatView;
if(!thatView) {
thatView = [[UIView alloc] init];
[self.view addSubView:thatView];
}
Once you release the superview, release thatView & make thatView to nil.
OR
always check & remove thatView if present from superview before allocating thatView.
Hope this Helps !!!