为啥自定义 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 属性的主要内容,如果未能解决你的问题,请参考以下文章

使用自定义 uiview xib

Xib 自定义 UIView 的实例化

如何将额外参数传递给链接到 XIB 文件的自定义 UIView?

如何借助 AutoLayout 在自定义 UITableviewCell 中添加自定义 UIView(xib)?

使用 XIB 创建自定义 UIView

自定义 UIView XIB 内的 iOS 导航返回按钮(无导航控制器)