为 StoryBoard 中 ViewController 中使用的 UIView 加载 Nib

Posted

技术标签:

【中文标题】为 StoryBoard 中 ViewController 中使用的 UIView 加载 Nib【英文标题】:Load Nib for UIView used in ViewController in StoryBoard 【发布时间】:2014-02-03 13:12:10 【问题描述】:

我有一个要在多个视图控制器中使用的 UIView,因此我为它创建了视图 (.h/.m) 和一个 nib 文件。在 Storyboard 中,视图作为子视图添加到视图控制器,但未加载 nib 中定义的布局。

是否可以为 Storyboard 的视图控制器中使用的 UIView 加载 nib?

【问题讨论】:

这是Swift example 【参考方案1】:

如果您在编辑 Storyboard 时询问在 Interface Builder 中查看 .xib 内容,这是不可能。但如果您需要在运行时加载它,有可能

.h/.m 应包含 UIView 子类 在 .xib 文件中,您需要使用自定义 UIView 子类设置 文件所有者Identity Inspector -> Custom Class) 在 .h 文件中添加 @property (strong, nonatomic) IBOutlet UIView* view; 并将您的 View 容器从 Interface Builder 连接到此字段(Ctrl + 单击 在 View 上并将连接拖到上方 view .h 中的属性 将其他子视图连接到 .h.m 文件中您需要放置


- (void)awakeFromNib 
    NSString* nibName = @"Place here your Nib name without extension";
    if ([[NSBundle mainBundle] loadNibNamed:nibName owner:self options:nil]) 
        [self.view setFrame:[self bounds]];
        [self addSubview:self.view];
    

就是这样。将 View 移至 Storyboard 场景,将 Custom Class 更改为您的 FooView,在 View Controller 代码中导入 .h 并使用 IBOutlets 随心所欲。

祝你编码愉快

编辑

我想注意,根据awakeFromNibdocumentation,我们应该避免awakeFromNib 中的此类代码。

建议您在文件所有者对象与其关联的 nib 文件之间保持一对一的对应关系。使用相同的 File's Owner 对象加载两个 nib 文件会导致该对象的 awakeFromNib 方法被调用两次,这可能会导致某些数据结构以不希望的方式重新初始化。还建议您避免从 awakeFromNib 方法实现中加载其他 nib 文件。

【讨论】:

因此,如果我有 FooView.h/.m 和 FooView.xib 并已将 FooView 添加到 Storyboard 中的 ViewController 并在 ViewController 中创建它的 IBOutlet。我不清楚的是 FooView 的“视图”属性。是否需要,或者Storyboard的ViewController中定义的FooView可以用其他方式实例化或唤醒吗? @tiltem 通常你会同时创建 View Controller 和 .xib。因此,在这种情况下,所有顶视图容器(在 .xib 中)和 VC 中的 view 属性的所有绑定都是自动进行的。在这里,您想将 UIView 绑定到 .xib。所以你需要手动完成这个日常工作。但它也允许您在 .xib 和 Storyboard 中使用自动布局。这是最低的价格。现在清楚了吗? 你会发现这个link很有帮助 这是一个很少被描述但非常有价值的解释。我喜欢它。这里提到了同样的方法:onedayitwillmake.com/blog/2013/07/… 嗯.. 可能我没明白你在说什么。您是否建议在您正在加载的类中添加上述代码(loadNibNamed)?这不是无限循环吗?【参考方案2】:

将您的视图命名为ViewInNib,然后我们有:

    ViewInNib.h ViewInNib.m ViewInNib.xib

在你的故事板中,在视图控制器中放置一个placeholder UIView 组件,记得设置它的类ViewInNib,然后在ViewInNib.m

static BOOL isReplaced = NO;
- (id)awakeAfterUsingCoder:(NSCoder *)aDecoder

    if (!isReplaced) 
    
        isReplaced = YES;
        ViewInNib *replaced = [[[NSBundle mainBundle] loadNibNamed:@"ViewInNib" owner:nil options:nil] lastObject];
        replaced.frame = self.frame;
        replaced.translatesAutoresizingMaskIntoConstraints = NO;
        return replaced;
    
    isReplaced = NO;
    return self;

在这种方法中,我们将从 nib 加载的真实视图替换为情节提要中的视图。希望对您有所帮助。

【讨论】:

这很有趣,但我无法让它发挥作用。是否仍然需要像 Anton Gaeko 的回答那样设置文件的所有者?与该答案的方法相比,这有什么缺点吗? 现在,你可以试试“pod search XXNibBridge” 为什么我们在 if 块中设置 isReplaced = YES,如果我们在之后设置 isReplaced = NO?这不会覆盖 if 块中的设置吗?这是一个错误吗? 因为 if 语句中有一个返回值,所以永远无法将其设置为“否”。附带说明一下,无论如何都不需要该语句,因为它可以访问该代码的唯一方法是它已经设置为 no。【参考方案3】:

使用 XXNibBridge:

https://github.com/sunnyxx/XXNibBridge

超级简单易用,也可以与 Swift 一起使用。 全部归功于@sunnyxx

【讨论】:

我在 Swift 中使用成功,非常感谢!!

以上是关于为 StoryBoard 中 ViewController 中使用的 UIView 加载 Nib的主要内容,如果未能解决你的问题,请参考以下文章

如何以编程方式从课堂加载故事板?

为 StoryBoard 中 ViewController 中使用的 UIView 加载 Nib

Storyboard - 在 Storyboard 中为同一个 ViewController 创建两个不同的视图

在 iOS 中使用 Storyboard 将图像设置为 TableView 的背景

为啥我的 Storyboard 中的静态原型 UITableViewCells 显示为空白?

iOS 为iPhone和iPad创建不同的storyboard