我在XCode/iOS领域相对较新;我已经做了一些基于故事板的应用程序,但是我从来没有在整个nib/xib上下过功夫.我想对场景使用相同的工具来设计/布局可重用的视图/控件.因此,我为我的视图子类创建了第一个xib,并绘制了它:

在此处输入图像描述

我有我的插座连接和约束设置,就像我习惯在故事板上做的那样.我将我的File Owner类设置为自定义UIView子类.因此,我假设我可以用一些API实例化这个视图子类,它将被配置/连接,如图所示.

现在回到我的故事板,我想嵌入/重用这个.我在一个表格视图原型单元中这样做:

在此处输入图像描述

我看到了风景.我已经将它的类设置为我的子类.我已经为它创造了一个出口,这样我就可以操纵它了.

64美元的问题是,我在哪里/如何表明,仅仅在那里放置我的视图子类的一个空/未配置的实例是不够的,而是使用.我创建xib是为了配置/实例化它吗?如果在XCode6中,我可以输入用于给定UIView的XIB文件,这将非常酷,但我没有看到这样做的字段,所以我假设我必须在代码中的某个地方做一些事情.

(I do see other questions like this on SO, but haven't found any asking for just this part of the puzzle, or up to date with XCode6/2015)

使现代化

我可以通过实现我的表格单元格awakeFromNib来实现这类工作,如下所示:

- (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;
}

这有那么简单吗?还是我工作太辛苦了?

推荐答案

你就快到了.您需要在为其指定视图的自定义类中重写initWithCoder.

- (id)initWithCoder:(NSCoder *)aDecoder {
    if ((self = [super initWithCoder:aDecoder])) {
        [self addSubview:[[[NSBundle mainBundle] loadNibNamed:@"ViewYouCreated" owner:self options:nil] objectAtIndex:0]];
    }
    return self; }

完成后,故事板将知道在该视图中加载xib.

以下是更详细的解释:

这是你的UIViewController在故事板上的样子:

蓝色空间基本上是一个UIView,可以"容纳"你的xib.

这是您的xib:

在此处输入图像描述

有一个操作与上面的按钮相连,可以打印一些文本.

这是最终的结果:

在此处输入图像描述

第一个clickMe和第二个clickMe的区别在于,第一个clickMe是使用StoryBoard添加到UIViewController的.第二个是使用代码添加的.

Objective-c相关问答推荐

使用 NSArray 初始化对象数组

如何在 Cocoa 中创建字符串的 MD5 哈希?

为什么 NSDateFormatter 为这 4 个时区返回 nil 日期?

使用 CALayer 时无法编译代码

为什么我不用 * 声明 NSInteger

iOS performSelectorOnMainThread 有多个参数

在 iOS 和 Mac OS X 应用程序中使用 C++

.m 文件中的空@interface 声明是做什么用的?

避免NSArray 在被枚举时发生Mutations

[MFMailComposeViewController canSendMail] 什么时候返回 NO

distanceFromLocation - 计算两点之间的距离

Select 时 UITableViewCell 复选标记更改

Modal segue,导航栏消失

带有 NSBlockOperation 和队列的 NSURLSession

既然我正在使用 Core Data,如何对我的模型进行单元测试?

writeToFile:atomically: atomically 是什么意思?

如何创建 .dSYM 文件?

最大 CGFloat 值是否有常数?

字符串常量和字符串文字有什么区别?

Unwind Segue 在 iOS 8 中不起作用