Check if a subview is in a view

89,140

Solution 1

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()
    }
}

Solution 2

Try this:

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

Solution 3

    UIView *subview = ...;
    if([self.view.subviews containsObject:subview]) {
        ...
    }

Solution 4

The Swift equivalent will look something like this:

if(!myView.isDescendantOfView(self.view)) {
    self.view.addSubview(myView)
} else {
    myView.removeFromSuperview()
}

Solution 5

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]];         
    }
}
Share:
89,140
pmerino
Author by

pmerino

Software developer with experience with Ruby, Ruby on Rails, Java, HTML, CSS, PHP, C#, JavaScript, Bash, Objective-C, MySQL, Postgres, SQLite, MongoDB, Redis as well as UNIX system administration.

Updated on July 08, 2022

Comments

  • pmerino
    pmerino almost 2 years

    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];
        }
    
    }
    
  • pmerino
    pmerino over 12 years
    Doesn't works, just adds the view over it. I'll edit the code to show the real case
  • pmerino
    pmerino over 12 years
    Doesn't works, just adds the view over it. I'll edit the code to show the real case – zad0xsis 1 min ago edit
  • Admin
    Admin over 12 years
    @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 ?
  • pmerino
    pmerino over 12 years
    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 not
  • bshirley
    bshirley over 12 years
    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
  • paulmelnikow
    paulmelnikow over 12 years
    @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
    paulmelnikow over 12 years
    This is a slight modification of Michael Frederick's answer. Does it give different results from Vincent's code which uses isDescendantOfView:?
  • Lior Frenkel
    Lior Frenkel over 12 years
    awesome! sometimes it needs myView.view.superview, but it worked like magic for me. Thanks @MarkGranoff
  • Rhubarb
    Rhubarb over 11 years
    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
    Rhubarb over 11 years
    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
  • Thomas Kekeisen
    Thomas Kekeisen over 11 years
    @pmerino Congrats for being that lazy that you also copied "zad0xsis 1 min ago edit" :-)
  • Sami Samhuri
    Sami Samhuri almost 10 years
    It absolutely yields a different result. This only checks if it is a child view, not a grandchild or great grandchild, etc.
  • SimplyKiwi
    SimplyKiwi almost 8 years
    I think this is more expensive than the other solutions to be honest because it has to iterate through all subviews
  • Chirag Purohit
    Chirag Purohit over 6 years
    It worked for me. I am checking whether particular element exist in tableview cell or not
  • Ali Pacman
    Ali Pacman over 2 years
    I think the problem here is that if a view is a subview of a subview, it won't be found.