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

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

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

【问题讨论】:

标签: uiview uiviewcontroller uistoryboard nib iso


【解决方案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,然后我们有:

  1. ViewInNib.h
  2. ViewInNib.m
  3. 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 中使用成功,非常感谢!!
猜你喜欢
  • 2013-04-08
  • 2013-04-29
  • 1970-01-01
  • 2014-09-11
  • 1970-01-01
  • 1970-01-01
  • 2011-02-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多