【问题标题】:Removing View from its SuperView, Notifying the Subviews on iPhone从 SuperView 中删除视图,通知 iPhone 上的子视图
【发布时间】:2009-06-24 15:00:46
【问题描述】:

当视图从其超级视图中移除时会触发什么事件?它的子视图是否收到任何消息? 例如,我将 subview2 和 subview3 添加到 subview1 中,如下所示

super_view -> subview1 -> subview2 -> subview3

如果我删除 subview1 例如由

[subview1 removeFromSuperview]; 

它的子视图(subview2 和 subview3)收到什么事件?

有没有办法让子视图知道他们的超级视图被删除了?

【问题讨论】:

    标签: iphone cocoa-touch uikit uiview


    【解决方案1】:

    这取决于 subview2 和 subview3 的保留计数。如果您通过 [[UIView alloc] initWithFrame:frame] 创建它们,然后将它们添加为子视图,它们的保留计数将为 2。(或 3,如果您在保留属性中保留引用,即 self.subview2 = [[...

    因此,如果您希望在释放 subview1 时释放它们,请确保在将它们添加为子视图后再次释放它们,以便它们的保留计数只是作为子视图添加的单个计数。像这样的...

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

    【讨论】:

    • +1,简 - 很棒的网站/公司/生活...我很感兴趣,因为您的回答和图片...
    • 好吧,简,正如你所提到的,我在将子视图添加到超级视图后将其发布。但是当我删除超级视图时,[self removeFromSuperView] 说“subview1”; // 从 subview2 的 superview dealloc 中删除 subview1 不会被调用。 “removeFromSuperView”的文档提到调用它也会释放它。我错过了什么吗?谢谢,
    • 您必须在 subview2 上有一个额外的保留 - 没有看到我只能说的代码,抱歉。并为我的生活投赞成票?我喜欢它,尽管我确定我应该返回这一点或其他东西:-)
    【解决方案2】:

    由于这个问题仍然悬而未决,这里有一个答案:

    @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
    

    如果您需要相反的情况,以下是通知父视图其子视图正在退出的方式。

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

    它的子视图(subview2 和 subview3)收到什么事件?
    subview1 得到通知,但 subview2subview3 需要让 subview1 传递该消息(这不是自动完成的)。

    有没有办法让子视图知道他们的超级视图已被删除?
    为此,您可以制作一个简单的委托协议,也可以扩展 UIView

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

    不过,请记住,如果您真的想知道他们什么时候不再出现在屏幕上(而且他们没有超级视图这一事实对您的目标来说是次要的),所有子视图将通过上述方法的UIWindow镜像通知。

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

    【讨论】:

      【解决方案3】:

      我不认为 subviews(2,3) 在 subview1 本身被删除时会收到任何事件(至少文档中没有提到任何内容)。

      编辑

      再想一想...我相信当 subview1 被释放时 subviews(2,3) 本身不会收到事件。

      但是,如果 subview1 没有保留在其他地方,则作为 subview1 被释放的副作用,它的引用计数将达到 0 并且将被释放。在释放期间 subview1 将释放其所有子视图。

      在那种情况下他们会被释放,我不确定这是否是你所追求的。

      查看简的回答。

      【讨论】:

      • removeFromSuperView 的文档说,“接收器也被释放;”。不释放视图是否会释放其子视图?
      【解决方案4】:

      当一个视图从它的父视图中移除时,它的所有子视图也会被移除,从而导致retaincout 减一。

      看下面的代码片段:

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

      而控制台日志是这样的:

       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
      

      实际上在最后一个 NSLog 应用程序会崩溃,因为两个对象的 retainCount =0。

      希望这会有所帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-04-06
        • 1970-01-01
        相关资源
        最近更新 更多