如何在故事板场景中嵌入自定义视图xib? [英] How to embed a custom view xib in a storyboard scene?
问题描述
我在XCode / iOS世界中相对较新;我已经完成了一些不错的基于故事板的应用程序,但我并没有在整个nib / xib上扯掉我的东西。我想使用相同的工具为场景设计/布局可重用的视图/控件。所以我为我的视图子类创建了我的第一个xib并绘制了它:
I'm relatively new in the XCode/iOS world; I've done some decent sized storyboard based apps, but I didn't ever cut me teeth on the whole nib/xib thing. I want to use the same tools for scenes to design/layout a reusable view/control. So I created my first ever xib for my view subclass and painted it up:
我连接了插座并设置了约束,就像我以前在故事板中做的那样。我将文件所有者
的类设置为我的自定义 UIView
子类的类。所以我假设我可以用一些API实例化这个视图子类,它将如图所示配置/连接。
I have my outlets connected and constraints setup, just like I'm used to doing in the storyboard. I set the class of my File Owner
to that of my custom UIView
subclass. So I assume I can instantiate this view subclass with some API, and it will configured/connected as shown.
现在回到我的故事板中,我想嵌入/重用这个。我在表格视图原型单元格中这样做:
Now back in my storyboard, I want to embed/reuse this. I'm doing so in a table view prototype cell:
我有一个观点。我已将它的类设置为我的子类。我已经为它创建了一个插座,所以我可以操作它。
I've got a view. I've set the class of it to my subclass. I've created an outlet for it so I can manipulate it.
64美元的问题是在哪里/如何表明它只是放空/未配置是不够的我的视图子类的实例在那里,但要使用我创建的.xib来配置/实例化它?这真的很酷,如果在XCode6中,我可以输入XIB文件用于给定的UIView,但是我没有看到用于执行此操作的字段,因此我假设我必须在代码中执行某些操作。
The $64 question is where/how do I indicate that it's not enough to just put an empty/unconfigured instance of my view subclass there, but to use the .xib I created to configure/instantiate it? It would be really cool, if in XCode6, I could just enter the XIB file to use for a given UIView, but I don't see a field for doing that, so I assume I have to do something in code somewhere.
(我确实在SO上看到了这样的其他问题,但是没有找到任何关于这部分难题的问题,或者最新的XCode6 / 2015 )
我可以通过实施我的表来实现这一目标单元格 awakeFromNib
如下:
I am able to get this to kind of work by implementing my table cell's awakeFromNib
as follows:
- (void)awakeFromNib
{
// gather all of the constraints pointing to the uncofigured instance
NSArray* progressConstraints = [self.contentView.constraints filteredArrayUsingPredicate: [NSPredicate predicateWithBlock:^BOOL(id each, NSDictionary *_) {
return (((NSLayoutConstraint*)each).firstItem == self.progressControl) || (((NSLayoutConstraint*)each).secondItem == self.progressControl);
}]];
// fetch the fleshed out variant
ProgramProgressControl *fromXIB = [[[NSBundle mainBundle] loadNibNamed:@"ProgramProgressControl" owner:self options:nil] objectAtIndex:0];
// ape the current placeholder's frame
fromXIB.frame = self.progressControl.frame;
// now swap them
[UIView transitionFromView: self.progressControl toView: fromXIB duration: 0 options: 0 completion: nil];
// recreate all of the constraints, but for the new guy
for (NSLayoutConstraint *each in progressConstraints) {
id firstItem = each.firstItem == self.progressControl ? fromXIB : each.firstItem;
id secondItem = each.secondItem == self.progressControl ? fromXIB : each.secondItem;
NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem: firstItem attribute: each.firstAttribute relatedBy: each.relation toItem: secondItem attribute: each.secondAttribute multiplier: each.multiplier constant: each.constant];
[self.contentView addConstraint: constraint];
}
// update our outlet
self.progressControl = fromXIB;
}
这么简单吗?或者我为此工作太辛苦了?
Is this as easy as it gets then? Or am I working too hard for this?
推荐答案
你几乎就在那里。您需要覆盖您为视图指定的自定义类中的initWithCoder。
You're almost there. You need to override initWithCoder in your custom class you assigned the view to.
- (id)initWithCoder:(NSCoder *)aDecoder {
if ((self = [super initWithCoder:aDecoder])) {
[self addSubview:[[[NSBundle mainBundle] loadNibNamed:@"ViewYouCreated" owner:self options:nil] objectAtIndex:0]];
}
return self; }
一旦完成,StoryBoard就会知道在UIView中加载xib。
Once that's done the StoryBoard will know to load the xib inside that UIView.
以下是更详细的解释:
这就是你的 UIViewController
的样子喜欢你的故事板:
This is how your UIViewController
looks like on your story board:
蓝色空间基本上是一个将保持你的xib的UIView。
The blue space is basically a UIView that will "hold" your xib.
这是你的xib:
有一个Action连接到其上的按钮,它将打印一些文本。
There's an Action connected to a button on it that will print some text.
这是最终结果:
第一个clickMe与第二个之间的区别在于第一个被添加到 UIViewController
使用 StoryBoard
。第二个是使用代码添加的。
The difference between the first clickMe and the second is that the first was added to the UIViewController
using the StoryBoard
. The second was added using code.
这篇关于如何在故事板场景中嵌入自定义视图xib?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!