为 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 随心所欲。
祝你编码愉快
编辑
我想注意,根据awakeFromNib
documentation,我们应该避免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 的背景