Check if a subview is in a view
Asked Answered
G

7

100

I'm making an app where I add a subview to a view using addSubview: on an IBAction. In the same way, when the button with that IBAction is touched again should call removeFromSuperview on that subview added on that IBAction:

PSEUDO CODE

-(IBAction)showPopup:(id)sender 
{
    System_monitorAppDelegate *delegate = (System_monitorAppDelegate *)[[UIApplication sharedApplication] delegate];
    UIView *rootView = delegate.window.rootViewController.view;

    if([self popoverView] is not on rootView) 
    { 
        [rootView addSubview:[self popoverView]];
    } 
    else 
    {
        [[self popoverView] removeFromSuperview];
    }

}
Gosnell answered 14/9, 2011 at 18:38 Comment(0)
W
277

You are probably looking for UIView's -(BOOL)isDescendantOfView:(UIView *)view; taken in UIView class reference.

Return Value YES if the receiver is an immediate or distant subview of view or if view is the receiver itself; otherwise NO.

You will end up with a code like :

Objective-C

- (IBAction)showPopup:(id)sender {
    if(![self.myView isDescendantOfView:self.view]) { 
        [self.view addSubview:self.myView];
    } else {
        [self.myView removeFromSuperview];
    }
}

Swift 3

@IBAction func showPopup(sender: AnyObject) {
    if !self.myView.isDescendant(of: self.view) {
        self.view.addSubview(self.myView)
    } else {
        self.myView.removeFromSuperview()
    }
}
Wales answered 14/9, 2011 at 18:43 Comment(8)
Doesn't works, just adds the view over it. I'll edit the code to show the real caseGosnell
@zad0xsis - I don't understand the real case. If you added the second view using addSubview: method (which is probably the case the first time), the next time, you'll reach the else part because the second view now is a subview of the first. Isn't it what you were trying to do ? You are maybe looking another mecanism like prensenting a view controller modally ?Wales
well, popoverViewis a subview of rootView (rootViewController). I want to check if it's on screen (if it has rootView as superview) and if so remove it or else add it if it's notGosnell
is [self popoverView] returning a newly created popover each time? it cannot add a view "over it" if it's the same view, adding a view that's already there is a no-op. if the popoverView method is creating a new one every time, then it will always not be in the view hierarchyCenturion
@zad0xsis Would you clarify what you mean by "just adds the view over it"? Does that happen on the first call when the view should display, or on the second when the view should hide?Presage
One important consideration that tripped me up here: when removing then adding subviews that you're holding onto with IBOutlet properties (or ivars) you need to make sure the properties (ivars) are strong, or that (pre ARC) they're retain. By default if you ctrl-drag from a view to a controller to create an outlet, it will create it as weak because it assumes that the view created in the nib will own it so you dont need a strong reference. But if you then remove it programmatically, it will dealloc the control and set your reference to nil (in ARC).Postimpressionism
Note also that Objective-C is so lenient about calling methods on nil that you won't see any exception when your view references are dealloced only weird behaviour like missing viewsPostimpressionism
It worked for me. I am checking whether particular element exist in tableview cell or notAqua
T
19

Try this:

-(IBAction)showPopup:(id)sender
{
    if (!myView.superview)
        [self.view addSubview:myView];
    else
        [myView removeFromSuperview];
}
Tindle answered 14/9, 2011 at 18:41 Comment(1)
awesome! sometimes it needs myView.view.superview, but it worked like magic for me. Thanks @MarkGranoffHazem
B
11
    UIView *subview = ...;
    if([self.view.subviews containsObject:subview]) {
        ...
    }
Belligerence answered 14/9, 2011 at 18:43 Comment(3)
Doesn't works, just adds the view over it. I'll edit the code to show the real case – zad0xsis 1 min ago editGosnell
@Gosnell Congrats for being that lazy that you also copied "zad0xsis 1 min ago edit" :-)Ripping
I think this is more expensive than the other solutions to be honest because it has to iterate through all subviewsHyetography
L
4

The Swift equivalent will look something like this:

if(!myView.isDescendantOfView(self.view)) {
    self.view.addSubview(myView)
} else {
    myView.removeFromSuperview()
}
Limitative answered 16/6, 2015 at 10:2 Comment(0)
V
2

Check the superview of the subview...

-(IBAction)showPopup:(id)sender {
    if([[self myView] superview] == self.view) { 
        [[self myView] removeFromSuperview];           
    } else {
        [self.view addSubview:[self myView]];         
    }
}
Verisimilitude answered 14/9, 2011 at 18:41 Comment(0)
A
1

Your if condition should go like

if (!([rootView subviews] containsObject:[self popoverView])) { 
    [rootView addSubview:[self popoverView]];
} else {
    [[self popoverView] removeFromSuperview];

}
Alage answered 14/9, 2011 at 19:18 Comment(2)
This is a slight modification of Michael Frederick's answer. Does it give different results from Vincent's code which uses isDescendantOfView:?Presage
It absolutely yields a different result. This only checks if it is a child view, not a grandchild or great grandchild, etc.Locution
A
0

Here we used two different views. Parent view is the view in which we are searching for descendant view and check wether added to parent view or not.

if parentView.subviews.contains(descendantView) {
   // descendant view added to the parent view.
}else{
  // descendant view not added to the parent view.
}
Athey answered 27/7, 2020 at 6:0 Comment(1)
I think the problem here is that if a view is a subview of a subview, it won't be found.Continuo

© 2022 - 2024 — McMap. All rights reserved.