我试着做一些复杂的事情,但应该是可能的。所以这里有一个对你们所有专家的挑战(这个论坛是由你们很多人组成的:))。

我正在创建一个问卷“组件”,我想加载在一个navigationcontroller(我的QuestionManagerViewController)。“组件”是一个“空的”UIViewController,它可以根据需要回答的问题加载不同的视图。

我的做法是:

Create Question1View object as a UIView subclass, defining some IBOutlets. Create (using Interface Builder) the Question1View.xib (HERE IS WHERE MY PROBLEM PROBABLY IS). I set both the UIViewController and the UIView to be of class Question1View. I link the outlets with the view's component (using IB). I override the initWithNib of my QuestionManagerViewController to look like this: - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { if (self = [super initWithNibName:@"Question1View" bundle:nibBundleOrNil]) { // Custom initialization } return self; }

当我运行代码时,我得到这个错误:

2009-05-14 15:05:37.152 iMobiDines[17148:20b] ***由于未捕获异常'NSInternalInconsistencyException'而终止应用程序,原因:'-[UIViewController _loadViewFromNibNamed:bundle:] loaded the "Question1View" nib but the view outlet was not set.'

我确信有一种方法可以使用nib文件加载视图,而不需要创建一个viewController类。


当前回答

没有一个答案解释如何创建独立的XIB,这是这个问题的根源。Xcode 4没有“创建新的XIB文件”选项。

要做到这一点

1) Choose "New File..."
2) Choose the "User Interface" category under the iOS section
3) Choose the "View" item
4) You will then be prompted to choose an iPhone or iPad format

这看起来很简单,但它可以为您节省几分钟的时间,因为“XIB”这个词没有出现在任何地方。

其他回答

你也可以使用UIViewController的initWithNibName而不是loadnibname。我发现这样更简单。

UIViewController *aViewController = [[UIViewController alloc] initWithNibName:@"MySubView" bundle:nil];
[self.subview addSubview:aViewController.view];
[aViewController release];  // release the VC

现在你只需要创建MySubView。xib和MySubView.h/m。在MySubView。xib设置文件的Owner类为UIViewController,视图类为MySubView。

您可以使用父xib文件来定位子视图的位置和大小。

下面是一种在Swift中实现的方法(目前正在XCode 7 beta 5中编写Swift 2.0)。

从你在接口构建器中设置为“自定义类”的UIView子类中创建一个像这样的方法(我的子类叫做RecordingFooterView):

class func loadFromNib() -> RecordingFooterView? {
    let nib = UINib(nibName: "RecordingFooterView", bundle: nil)
    let nibObjects = nib.instantiateWithOwner(nil, options: nil)
    if nibObjects.count > 0 {
        let topObject = nibObjects[0]
        return topObject as? RecordingFooterView
    }
    return nil
}

然后你可以像这样调用它:

let recordingFooterView = recordingFooterView . loadfromnib ()

我不确定一些答案在谈论什么,但我需要把这个答案放在这里,当我下次在谷歌中搜索时。关键词:“如何从一个nib加载一个UIView”或“如何从一个NSBundle加载一个UIView”

下面的代码几乎100%直接来自Apress Beginning iPhone 3的书籍(第247页,“使用新的表视图单元格”):

- (void)viewDidLoad {
    [super viewDidLoad];
    NSArray *bundle = [[NSBundle mainBundle] loadNibNamed:@"Blah"
                                                 owner:self options:nil];
    Blah *blah;
    for (id object in bundle) {
        if ([object isKindOfClass:[Blah class]]) {
            blah = (Blah *)object;
            break;
        }
    }   
    assert(blah != nil && "blah can't be nil");
    [self.view addSubview: blah];
} 

这假设你有一个UIView子类叫Blah,一个nib叫Blah它包含一个UIView它的类设置为Blah。


类别:+ LoadFromNib NSObject

#import "NSObject+LoadFromNib.h"

@implementation NSObject (LoadFromNib)

+ (id)loadFromNib:(NSString *)name classToLoad:(Class)classToLoad {
    NSArray *bundle = [[NSBundle mainBundle] loadNibNamed:name owner:self options:nil];
    for (id object in bundle) {
        if ([object isKindOfClass:classToLoad]) {
            return object;
        }
    }
    return nil;
}

@end

迅速扩展

extension UIView {
    class func loadFromNib<T>(withName nibName: String) -> T? {
        let nib  = UINib.init(nibName: nibName, bundle: nil)
        let nibObjects = nib.instantiate(withOwner: nil, options: nil)
        for object in nibObjects {
            if let result = object as? T {
                return result
            }
        }
        return nil
    }
}

还有一个正在使用的例子:

class SomeView: UIView {
    class func loadFromNib() -> SomeView? {
        return self.loadFromNib(withName: "SomeView")
    }
}

没有一个答案解释如何创建独立的XIB,这是这个问题的根源。Xcode 4没有“创建新的XIB文件”选项。

要做到这一点

1) Choose "New File..."
2) Choose the "User Interface" category under the iOS section
3) Choose the "View" item
4) You will then be prompted to choose an iPhone or iPad format

这看起来很简单,但它可以为您节省几分钟的时间,因为“XIB”这个词没有出现在任何地方。

我也想做一些类似的事情,这是我发现的: (SDK 3.1.3)

我有一个视图控制器a(本身由一个导航控制器拥有),它在一个按钮按下加载VC B:

在AViewController.m

BViewController *bController = [[BViewController alloc] initWithNibName:@"Bnib" bundle:nil];
[self.navigationController pushViewController:bController animated:YES];
[bController release];

现在VC B有它的接口从Bnib,但当一个按钮被按下,我想去一个“编辑模式”有一个独立的UI从不同的nib,但我不想要一个新的VC的编辑模式,我想新的nib与我现有的B VC相关联。

在BViewController中。M(按按钮方式)

NSArray *nibObjects = [[NSBundle mainBundle] loadNibNamed:@"EditMode" owner:self options:nil];
UIView *theEditView = [nibObjects objectAtIndex:0];
self.editView = theEditView;
[self.view addSubview:theEditView];

然后按下另一个按钮(退出编辑模式):

[editView removeFromSuperview];

我又变回了原来的Bnib

这很好,但请注意我的EditMode。nib中只有一个顶级obj,一个UIView obj。 不管这个nib中的文件所有者是设置为BViewController还是默认的NSObject,但要确保文件所有者中的视图出口没有设置为任何东西。 如果是,那么我得到一个exc_bad_access崩溃,xcode继续加载6677个堆栈帧 显示一个内部UIView方法被反复调用…看起来像一个无限循环。 (视图出口是设置在我原来的Bnib然而)

希望这能有所帮助。