Removing View from its SuperView, Notifying the Subviews on iPhone

15,561

Solution 1

It depends on the retain count of subview2 and subview3. If you create them via [[UIView alloc] initWithFrame:frame], and then add them as subviews, they will have a retain count of 2. (Or 3, if you keep a reference in a retained property, i.e. self.subview2 = [[...

So if you want them to be released when subview1 is released, then ensure you give them another release after adding them as a subview, so that their retain count is just the single one from being added as a subview. Something like this...

UIView* subview2 = [[UIView alloc] initWithFrame:myFrame];
[subview1 addSubview:subview2];
[subview2 release];

Solution 2

Since this question is still open, here's an answer:

@implementation MySubview
- (void)willMoveToSuperview:(UIView *)newSuperview {
  if (!newSuperview) {
    // I'm being removed from my superview.
  }
}
- (void)didMoveToSuperview {
  if (!self.superview) {
    // I no longer have a superview.
  }
}
@end

If you need the opposite, here's how the superview is notified that its subview is peacing out.

@implemenation MySuperview
- (void)willRemoveSubview:(UIView *)subview {
  // I'm about to remove this view.
}
@end

What event its subviews(subview2 and subview3) receive?
subview1 is notified, but subview2 and subview3 would need to have that message passed on by subview1 (which isn't done automatically).

Is there a way to let subviews know that their super view is removed?
You could make a simple delegate protocol or you could extend UIView for this purpose.

@implementation UIView (superview_notification)
- (void)notifyMyChildrenAboutTheSuperviewChange {
  [[self subviews] makeObjectsPerformSelector:@selector(notifyMyChildrenAboutTheSuperviewChange)];
}
@end

Keep in mind, however, that if you're really wanting to know when they're no longer on the screen at all (and the fact that they don't have a superview is secondary to your goal), all of the subviews will be notified through the UIWindow mirrors of the above methods.

@implementation MySubview
- (void)willMoveToWindow:(UIWindow *)newWindow {
  if (!newWindow) {
    // I'm being removed from the screen.
  }
}
- (void)didMoveToWindow {
  if (!self.window) {
    // I'm offscreen.
  }
}
@end
Share:
15,561
MAbbas
Author by

MAbbas

Updated on June 04, 2022

Comments

  • MAbbas
    MAbbas almost 2 years

    What event is fired when a view is removed from its super view? Do its sub-views receive any message? For example, I have subview2 and subview3 added to subview1 as in

    super_view -> subview1 -> subview2 -> subview3

    if I remove subview1 e.g. by

    [subview1 removeFromSuperview]; 
    

    What event its subviews(subview2 and subview3) receive?

    Is there a way to let subviews know that their super view is removed?

  • MAbbas
    MAbbas almost 15 years
    The documentation for removeFromSuperView says, "The receiver is also released;". Does not releasing a view releases its subviews?
  • Nubzor
    Nubzor almost 15 years
    +1, Jane - great web site/company/life ... I was intrigued because of your answer&pic ...
  • MAbbas
    MAbbas almost 15 years
    Well Jane, As you mentioned, I am releasing the subview after adding it to a super view. But when I remove the super view say "subview1" by [self removeFromSuperView]; // Removing subview1 from its superview dealloc for subview2 is not called. The documentation for "removeFromSuperView" mentions that callin it will release it also. Am I missing something? Thanx,
  • Jane Sales
    Jane Sales almost 15 years
    You must have an extra retain on subview2 - without seeing the code that's all I can say, sorry. And an up vote for my life? I like it, though I'm sure I should return the point or something :-)