为啥自定义 xib 需要 UIView 属性

Posted

技术标签:

【中文标题】为啥自定义 xib 需要 UIView 属性【英文标题】:Why does custom xib require UIView property为什么自定义 xib 需要 UIView 属性 【发布时间】:2015-11-05 19:16:43 【问题描述】:

我按照此处概述的教程在我的视图控制器中加载自定义 xib。

xib的类继承自UIView但也需要一个属性视图:

 @interface MYBannerView : UIView
 @property (nonatomic, weak) IBOutlet UIView *view;
 @end  

我觉得它需要这个很奇怪,因为它就像在一个看起来多余的视图中拥有一个视图。这有什么特别的原因吗?

编辑

我在这里按照本教程进行了概述:

http://www.maytro.com/2014/04/27/building-reusable-views-with-interface-builder-and-auto-layout.html

【问题讨论】:

理论上你不需要这个属性,你可以使用self... 为什么需要它?你在哪里读到的? 我添加了我用作教程的原始链接 下面给出具体答案。但实际上,如果您正在学习 ios,那么您应该将 CONTAINER VIEWS 用于任何类似的事情。现在一切都是容器视图。它们使用起来绝对是微不足道的——这是 Apple 在编程效率方面的惊人进步。 Long tutorial 关于具体问题,我真的强烈建议您忽略您链接到的特定教程。如果 - 出于某种原因 - 你想这样做。 (或者,如果您正在使用 1990 年的时间机器阅读这篇文章,当时还没有简单的容器视图 :))... 就这样做***.com/a/21073901/294884 更多关于同一主题的信息... ***.com/a/25910881/294884 【参考方案1】:

MYBannerView 以编程方式初始化时,该教程的作者正在使用视图出口从 xib 加载视图

- (instancetype)initWithCoder:(NSCoder *)aDecoder

    self = [super initWithCoder:aDecoder];
    if (self) 
        NSString *className = NSStringFromClass([self class]);
        self.view = [[[NSBundle mainBundle] loadNibNamed:className owner:self options:nil] firstObject];
        [self addSubview:self.view];
        return self;
    
    return nil;

在 Interface Builder 中创建的任何内容都不会使用程序化 init 加载。 loadNibNamed 从 xib 加载 UI。

如果您想覆盖 initWithFrame: 以从 xib 加载 UI 元素,您的 init 方法将如下所示:

- (instancetype)initWithFrame:(CGRect)frame

    self = [super initWithFrame:frame]; // initialize your objects

    if (self) 
        [[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class]) owner:self options:nil]; // load your view from IB
    

    return self; // return the view with all of the IB UI loaded

【讨论】:

仍然不是 100% 清楚。据我了解,当以编程方式加载 XIB 时,将调用 initWithFrame 并且仅在使用 IB 中的相关类设置 UIView 时才调用 initWithCoder。我想要得到的是:是否可以创建一个 XIB,将带有 IB 的 UI 组件添加到文件所有者,然后使用 initWithFrame 以编程方式初始化。 为了初始化使用界面生成器创建的任何 UIView 对象,您必须调用 loadNibNamed: 以便从 xib 加载视图。我编辑了我的帖子以显示initWithFrame: 的示例 感谢您迄今为止的建议。所以澄清一下,如果我要通过 IB 在 XIB 上添加一些按钮和标签,然后以编程方式加载 IB(这将调用 initWithFrame),那么这些标签和按钮不会加载? 不完全。如果您以编程方式调用任何 init 方法(init:initWithCoder:initWithFrame:),除非您覆盖初始化程序以调用 loadNibNamed:,否则不会加载界面构建器视图。 您可以在此问题中阅读有关此行为的更多信息:***.com/q/21722805/2415822【参考方案2】:

不,您的UIView 子类不需要视图的出口才能正常工作。事实上,使用self 您可以访问视图本身。 教程呢:当作者在MYViewController's 视图上添加view A(我们这样称呼它)时,他将view A 类设置为MYBannerView。正在运行的应用程序不会显示任何内容,因为 MYBannerView xib 没有加载并且没有替换来自 view A 的内容。所以作者在initWithCoder 中加载这个xib,使用loadNibNamed: 返回的值设置出口,并将从MYBannerView 加载的视图添加到view A。这个过程有点混乱,但它有效。

【讨论】:

以上是关于为啥自定义 xib 需要 UIView 属性的主要内容,如果未能解决你的问题,请参考以下文章