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];
    }

}
P.J.Radadiya
  • 1,493
  • 1
  • 12
  • 21
pmerino
  • 5,900
  • 11
  • 57
  • 76

7 Answers7

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()
    }
}
palme
  • 2,499
  • 2
  • 21
  • 38
  • 2
    Doesn't works, just adds the view over it. I'll edit the code to show the real case – pmerino Sep 14 '11 at 18:47
  • @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 ? –  Sep 14 '11 at 18:57
  • well, `popoverView`is 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 not – pmerino Sep 14 '11 at 19:09
  • 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 hierarchy – bshirley Sep 15 '11 at 00:59
  • @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? – paulmelnikow Sep 15 '11 at 02:57
  • 1
    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). – Rhubarb Nov 01 '12 at 17:24
  • 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 views – Rhubarb Nov 01 '12 at 17:24
  • It worked for me. I am checking whether particular element exist in tableview cell or not – Chirag Purohit Nov 16 '17 at 17:31
19

Try this:

-(IBAction)showPopup:(id)sender
{
    if (!myView.superview)
        [self.view addSubview:myView];
    else
        [myView removeFromSuperview];
}
Mark Granoff
  • 16,878
  • 2
  • 59
  • 61
11
    UIView *subview = ...;
    if([self.view.subviews containsObject:subview]) {
        ...
    }
Michael Frederick
  • 16,664
  • 3
  • 43
  • 58
4

The Swift equivalent will look something like this:

if(!myView.isDescendantOfView(self.view)) {
    self.view.addSubview(myView)
} else {
    myView.removeFromSuperview()
}
Alex Zavatone
  • 4,106
  • 36
  • 54
JaySH
  • 546
  • 6
  • 15
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]];         
    }
}
Jason Harwig
  • 43,743
  • 5
  • 43
  • 44
1

Your if condition should go like

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

}
Saran
  • 6,274
  • 3
  • 39
  • 48
  • This is a slight modification of Michael Frederick's answer. Does it give different results from Vincent's code which uses `isDescendantOfView:`? – paulmelnikow Sep 15 '11 at 02:59
  • It absolutely yields a different result. This only checks if it is a child view, not a grandchild or great grandchild, etc. – Sami Samhuri Jul 30 '14 at 01:41
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.
}
shubham
  • 611
  • 7
  • 16