简体   繁体   中英

Removing View from its SuperView, Notifying the Subviews on iPhone

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 eg 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?

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, ie 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];

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

I don't think that subviews(2,3) will receive any event when subview1 is removed per se (at least nothing is mentioned in documentation).

EDIT :

Thinking about it more ... I believe that the subviews(2,3) will not receive event per se when the subview1 is released.

But as a side effect of subview1 getting released if subview1 is not retained somewhere else its ref count will reach 0 and it will get deallocated. During deallocation subview1 will release all its subviews.

In that case they will get released, I'm not sure if this is what you are after.

See Jane's answer.

when a view is removed from its superview, all its child view is also removed from it resulting in reduction of retaincout by one.

Look at the following code snipet:

randomImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"oldbg.png"]];
randomImage.frame = CGRectMake(10, 10, 20, 20);

aview = [[UIView alloc] initWithFrame:CGRectMake(0,0, 320, 200)];

NSLog(@"aview retain=%d,image retain=%d",[aview retainCount],[randomImage retainCount]);

[aview addSubview:randomImage];
NSLog(@"aview retain=%d,image retain=%d",[aview retainCount],[randomImage retainCount]);
[randomImage release];
NSLog(@"aview retain=%d,image retain=%d",[aview retainCount],[randomImage retainCount]);


[self.view addSubview:aview];
NSLog(@"aview retain=%d,image retain=%d",[aview retainCount],[randomImage retainCount]);
[aview release];
NSLog(@"aview retain=%d,image retain=%d",[aview retainCount],[randomImage retainCount]);

[aview removeFromSuperview];
NSLog(@"aview retain=%d,image retain=%d",[aview retainCount],[randomImage retainCount]);

And the console log is like this:

 2009-08-09 23:29:42.512 ActionSheetTest[744:20b] aview retain=1,image retain=1
2009-08-09 23:29:42.513 ActionSheetTest[744:20b] aview retain=1,image retain=2
2009-08-09 23:29:42.515 ActionSheetTest[744:20b] aview retain=1,image retain=1
2009-08-09 23:29:42.516 ActionSheetTest[744:20b] aview retain=2,image retain=1
2009-08-09 23:29:42.517 ActionSheetTest[744:20b] aview retain=1,image retain=1

actually at the last NSLog the app will crash, since both of the objets has retainCount =0.

Hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM