在另一个xib中使用xib对象

时间:2011-02-23 18:31:18

标签: iphone objective-c cocoa-touch interface-builder uibutton

我正在设计使用IB特定按钮(带有一些标签,以及imageView和其他东西)。

我希望在另一个xib中使用该xib对象(按钮),其中我有6个该按钮的对象。

我知道我可以使用类标识符以编程方式执行此操作,但是我必须定位我的标签和图像视图,并在代码中设置默认值和其他所有内容。

我想知道是否可以仅使用IB做同样的事情? (当然我仍然会在代码中设置值,但我想要在lable / imageView的位置以及所有其余的在xib中设置)

由于

修改

所以,我理解我最初要求的是不可能的。 我现在正在尝试的是:

我创建了一个ButtonTest.xib。 在Xib里面我有一个UIView和3个子视图(2个标签和一个按钮)。 在检查器中,我将UIView类设置为ButtonTest。 在ButtonTest.m内部,每个子视图都有3个出口,我在IB中连接。

接下来我有ButtonTestViewController.xib。 在其中我放置了一个视图,并将它在检查器中的类设置为ButtonTest。 我将该视图与myTextView

ButtonTestViewController.m内的ButtonTest出口相关联

现在,这是ButtonTestViewController.m viewDidLoad:

中的代码
- (void)viewDidLoad {
    [super viewDidLoad];

    NSArray *subviewArray = [[NSBundle mainBundle] loadNibNamed:@"ButtonTest" owner:nil options:nil];
    ButtonTest *mainView = (ButtonTest*)[subviewArray objectAtIndex:0];

    self.myTextView = mainView;
}

我希望会发生的是,ButtonTestViewController.xib中的视图将成为我在ButtonTest.xib中设计的视图。 这不会发生。会发生什么是ButtonTestViewController.xib中的视图保持不变。

值得一提的是,如果我加上:

[self.view addSubview:mainView];

除了现有视图之外,它还会添加新视图。

知道如何做我想做的事吗?

最终我想在ButtonTestViewController.xib中有6个视图,所有视图都类似于ButtonTest.xib模板,而lables值将在代码中设置。

EDIT2

好吧,伙计们,我做了你说的一切,它就像一个魅力。 我现在遇到的唯一问题是ButtonTestViewController.xib中的视图比ButtonTest.xib中的视图大一点。 当发生这种情况时,按钮上的标签看起来非常模糊。 当它们都是相同的尺寸时,一切都很好。

@Ned - 我使用了你在我的InitWithCoder方法中发布的确切代码,除了我将框架句子改为:

self.bounds = mainView.frame;

我尝试使用IB中的内容模式尝试修复它,但无济于事。

当我像你发布的那样使用它时,意思是:

mainView.frame = self.bounds;

它根本不起作用,两个视图的大小保持不变。 在这里,我尝试使用resizeMask,但仍然无法正常工作。

并想知道如何解决这两个问题? 谢谢你们!

编辑3

我确实设法修复了其中一个问题,将ButtonTestViewController.xib的大小调整为ButtonTest.xib视图大小。 这就是我所做的(使用代码解决模糊问题,取自here

self.bounds = CGRectMake(0, 0, mainView.frame.size.width, mainView.frame.size.height);
        CGRect overlay2Frame = self.frame;
        overlay2Frame.origin.x = round(overlay2Frame.origin.x);
        overlay2Frame.origin.y = round(overlay2Frame.origin.y);
        self.frame = overlay2Frame;

另一个问题我仍然无法解决。 ButtonTest.xib中的视图不会变得更大以匹配其他视图。

4 个答案:

答案 0 :(得分:16)

你可以很容易地做到这一点。我这样做的方法是创建一个UIView子类(让我们说它叫做“MyView.m”和“MyView.h”),然后创建一个名为“MyView.xib”的笔尖。

首先,在nib中,单击File的Owner,然后将类设置为“MyView”。这将使你的班级IBOutlets / Actions出现在IB中。添加一个顶级视图(如果它还没有)作为主视图,并添加其他自定义元素(UILabels和UIImageViews)作为主UIView的子视图。

接下来,添加以下代码,以便在初始化MyView时调用它(请记住,如果从nib初始化它将通过 - (id)initWithCoder:(NSCoder *)aDecoder初始化)。

NSArray *subviewArray = [[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class]) owner:self options:nil];
UIView *mainView = [subviewArray objectAtIndex:0];

//Just in case the size is different (you may or may not want this)
mainView.frame = self.bounds;

[self addSubview:mainView];

这样做是将视图层次结构从您的nib加载到NSArray中,并且因为您只有一个顶级UIView,所以您只需将其添加为自定义UIView的子视图。

这允许您在Interface Builder中设计UIViews(以及UIView的其他子类)。

编辑:已更新为OP的编辑。

我一直这样做的方法是先按照上面的说明操作。一个区别是你的ButtonTest笔尖你正在将UIView的类更改为ButtonTest,但我将文件所有者的类更改为ButtonTest。然后,在ButtonTest.m内,执行loadNibNamed内容。现在,要将该对象添加到ButtonTestViewController.xib,添加一个UIView(或UIButton,无论ButtonTest是否为子类),并将该类更改为ButtonTest。

这有点令人困惑,所以我会尝试按文件分解。

ButtonTestViewController.xib:添加一个UIButton(无论ButtonTest继承的是什么)并将类更改为ButtonTest

ButtonTest.m:在“initWithCoder”方法中,执行上面的所有“loadNibNamed”内容

ButtonTest.xib:将文件的所有者类更改为ButtonTest并链接所有IBOutlet和IBActions

答案 1 :(得分:6)

有些人在评论中是否说这个解决方案没有创建无限循环而且我没有足够的声誉来回答那里,所以这是我的回答:

如果XIB中的根视图具有"自定义类"则存在循环。设置为MyView。这会导致从XIB加载的视图再次调用MyView 的初始化程序的情况,因此会创建无限循环。解决方案是" Custom class"应该是UIView,只有文件所有者的类应该设置为MyView(能够分配IBOutlets和IBActions)。

答案 2 :(得分:2)

Swift 3.0

使用类

创建swift文件
class ViewXIBfileClassView: UIView {
.....
}

使用视图创建 Xib 文件:ViewXIBfileClassView

创建包装器视图类

class ViewWrapper: UIView {

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        let view = UINib(nibName: "ViewXIBfileClassView_file", bundle: nil).instantiate(withOwner: nil, options: nil)[0] as! viewXIBfileClassView
        self.addSubview(view)
        view.bindEdgesToSuperview()
    }
}

将扩展名添加到 UIView

extension UIView {
    /// Adds constraints to the superview so that this view has same size and position.
    /// Note: This fails the build if the `superview` is `nil` – add it as a subview before calling this.
    func bindEdgesToSuperview() {
        guard let superview = superview else {
            preconditionFailure("`superview` was nil – call `addSubview(view: UIView)` before calling `bindEdgesToSuperview()` to fix this.")
        }
        translatesAutoresizingMaskIntoConstraints = false
        ["H:|-0-[subview]-0-|", "V:|-0-[subview]-0-|"].forEach { visualFormat in
            superview.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: visualFormat, options: .directionLeadingToTrailing, metrics: nil, views: ["subview": self]))
        }
    }
}

在您想要的所有Xib文件中使用 UIView ViewWrapper

答案 3 :(得分:-1)

例如,如果您的类是UIButton的子类,则可以在Interface Builder中打开该库,当您搜索它时它将位于“类”选项卡下,您可以拖放。

您也可以拖放UIButton并在检查器窗格中设置其类。

但是,因为你有自己的.xib可能会弄乱它,在这种情况下只是忽略我。