【问题标题】:Possible to make superView intercept layoutSubviews: from subviews?可以让superView拦截layoutSubviews:来自子视图吗?
【发布时间】:2011-10-24 01:54:23
【问题描述】:

为了实现灵活的布局,我想创建一个 UIView 子类,它会覆盖 layoutSubviews: 以自动将其所有子视图布局在彼此之下,并且每次调整其子视图的大小时都会继续这样做。

但是,我能想到的让超级视图知道它应该调用 layoutSubviews: 的唯一方法是在其每个子视图中覆盖该方法,这是我想尝试避免的(我希望人们能够将任意 UIViews 添加到 superview 并进行处理)。

有没有办法让超级视图在子视图更改其大小时调用layoutSubviews:无需向相关子视图添加任何代码?

【问题讨论】:

    标签: iphone cocoa-touch uiview uikit layoutsubviews


    【解决方案1】:

    您可以使用 KVO 观察每个子视图的 frame 属性。每次添加子视图时,您都需要将自己添加为观察者,并在删除子视图时删除观察 - 您可以在超级视图中覆盖 didAddSubview:willRemoveSubview: 来做到这一点。

    - (void)didAddSubview:(UIView *)subview {
        [subview addObserver:self forKeyPath:@"frame" options:NSKeyValueObservingOptionNew context:nil];
    }
    
    - (void)willRemoveSubview:(UIView *)subview {
        [subview removeObserver:self forKeyPath:@"frame"];
    }
    
    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
        if ([keyPath isEqualToString:@"frame"]) {
             // Do your layout here...
        }
    }
    
    - (void)dealloc {
        // You might need to remove yourself as an observer here, in case
        // your subviews are still used by others
    }
    

    【讨论】:

      【解决方案2】:

      您可以向该类添加一个类别并尝试从该类别中覆盖layoutSubviews:。 (这种技术has been suggested for customizing navigation bars,在这里也可以很好地工作。)

      这是创建类别的方法,taken from my answer here。在您的情况下,请记住将 UIView 替换为 UINavigationController

      按 Command+N 或打开“新建文件”对话框。接下来,从 Cocoa Touch 菜单中选择“Objective-C 类别”:

      单击下一步,系统将提示您输入要添加方法作为类别的类的名称。它应该看起来像这样:

      然后,您应该会看到一个保存文件对话框。这里是关于约定的快速说明。约定是在原始类、加号之后命名一个类别,然后是您要添加的内容的描述。您的可能如下所示:

      一旦你保存了你的文件,你需要得到这样的东西:

      编辑:

      如果您想继续并在没有类别的情况下执行此操作,那么您最好的选择是创建 UIView 的子类,然后将 that 类子类化到您想要自定义行为的任​​何位置。与类别相比的另一个优势是,您的方法仅适用于您明确使用自定义类的情况。在类别中,该方法被添加到任何地方。

      祝你好运!

      【讨论】:

      • 很好的答案,但问题是错误的。我已经知道如何创建类别,并且我编辑了我原来的问题,因为我知道在类别中覆盖方法是一个很大的禁忌。子类化是你应该如何做到这一点。真正的问题是:有没有办法让超级视图在子视图改变其大小时自动调用layoutSubviews:而不向子视图添加任何代码?
      • 我建议创建一个“两级”层次结构。在第一个子类中自定义方法一次,然后子类that
      • 我也是这么想的,但我想知道是否有比将所有子视图更改为子类that 更优雅的解决方案。我会再给它一些时间,看看其他人是否有其他想法。你的回答是“不,不是”。之后会被接受;)感谢您的评论。
      • @Spacy 当然,没问题。我会编辑我的答案,所以如果你最终接受它,你可以接受它。 ;-)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-19
      • 2023-03-21
      相关资源
      最近更新 更多