【问题标题】:Loading XIB file without a UIViewController在没有 UIViewController 的情况下加载 XIB 文件
【发布时间】:2013-03-14 19:06:09
【问题描述】:

我想使用 Interface Builder 设计一个 UIView 和一些子视图(UIWebView、UIToolbar、一些 UIBarButtonItems、一个进度指示器等等),但我认为传统上没有必要这样做,通过使用UIViewController,使用presentViewController:animated

所以,我创建了一个自定义类,.h 文件代码如下:

@interface FileInteractionManager : NSObject {

}

@property (nonatomic, retain) IBOutlet UIView *fileView;
@property (nonatomic, retain) IBOutlet UIWebView *fileWebView;

@property (nonatomic, retain) IBOutlet UIBarButtonItem *printButton;
@property (nonatomic, retain) IBOutlet UIBarButtonItem *optionsButton;
@property (nonatomic, retain) IBOutlet UIBarButtonItem *doneButton;

我的.m文件如下:

@implementation FileInteractionManager

@synthesize fileView, fileWebView, doneButton, optionsButton, printButton;

-(id)init {

    NSArray *array = [[NSBundle mainBundle] loadNibNamed:@"FileInteractionView" owner:self options:nil];

    NSLog(@"Load success!");

    return self;
}

最后,我创建了一个名为“FileInteractionView.xib”的独立 xib 文件,将文件的所有者更改为我在上面创建的自定义类,然后连接 IBOutlets。

当我在我的类上调用 init 方法时,我可以在调试器中看到我的所有 IBOutlet 对象都已正确实例化。

我的问题是:

  1. loadNibNamed:owner:options: 方法是加载独立 .xib 文件的正确方法吗?我不喜欢这个方法返回一个我没用的数组(返回的顶级对象与我的变量fileView 匹配,但我已经通过Interface Builder 链接了它们)。

  2. 我的一般方法在解决我的问题时是否正确?我执行上述步骤是因为我想要一个简单的 UIView 对象,我可以将它添加到现有的 UIViewController 中,而不是呈现和关闭一个全新的 UIViewController。

【问题讨论】:

    标签: objective-c xcode uiview interface-builder xib


    【解决方案1】:

    il Malvagio Dottor Prosciutto 的回答很好。这是一个可能的替代方案。

    在 NS_DESIGNATED_INITIALIZER 中加载 nib 并成为子视图的所有者

    如果我们接受xib 只保存一个子视图而不是视图本身,那么我们可以在initWithFrame: 中加载子视图并在xib 中保留所有权结构。

    @interface MyCustomView ()
    @property (strong, nonatomic) IBOutlet UIView *subview;
    @end
    
    @implementation MyCustomView
    - (instancetype)initWithFrame:(CGRect)frame
    {
        self = [super initWithFrame:frame];
        [[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class]) owner:self options:nil];
        [self addSubview:self.subview];
        return self;
    }
    @end
    

    【讨论】:

      【解决方案2】:

      我使用了一些不同的方法。我创建了 UIView 的子类(即 MyCustomView ),然后创建带有视图 UI 的 xib 并更改刚刚定义的(主)视图类。然后在 xib 中,您可以将插座链接到自定义视图本身(而不是文件所有者)。 最后在类定义中,我创建了一个这样的函数:

      + (id) newFromNib
      {
          NSArray *nibArray = [[UINib nibWithNibName:NSStringFromClass([self class]) bundle:nil] instantiateWithOwner:nil options:nil];
          return nibArray[0];
      }
      

      只是几个注意事项: 1)这是一个类方法,你可以将“self”用于“NSStringFromClass([self class])”之类的东西,但真正的对象是返回的变量 2) 这个例子假设 xib 具有相同的类名称(通过 NSStringFromClass([self class]) 所以我可以复制粘贴它而不改变任何东西;))并且你的视图是 xib 中定义的第一个视图(标准)。如果您在一个 xib 中存储多个“主”视图,请选择正确的元素。

      所以在我需要 MyCustomView 的地方,我会执行以下操作:

      MyCustomView* mycv = [MyCustomView newFromNib];
      

      然后设置框架/中心并添加到超级视图... 我认为如果你有一个复杂 UI 元素的“库”并且想通过 xib 设计它们然后在需要时添加,我认为这种方式非常有用。

      【讨论】:

      • 这是你应该使用的方法
      • 我不确定我是否完全理解答案。如何在不首先将类分配给文件所有者的情况下将 IBOutlet 链接到自定义视图?如果您的自定义视图有更多子视图怎么办?
      • 如果您将视图类设置为自定义视图,则无需指定文件所有者。 InterfaceBUilder 足够聪明,可以解析 MyCustomView.h 以查找 IBOutlet 和 IBAction。因此,您可以将子视图出口直接链接到 MyCustomView。 UI 可以任意复杂。我只是警告您,如果您在 xib 中放置多个“主”视图(不是常见的或最佳实践,但也许您需要它),它们将是 nibArray 中的不同元素,因此您必须选择正确的元素。通常你只有一个,所以它总是元素 0。
      • 谢谢,有帮助。如果您想从 nib 实例化多个 UIView 对象,这是否也能正常工作? (只是想知道,因为它是一个静态方法,我很快就会自己尝试一下)
      • 是的,您可以通过多次调用“newFromNib”方法来拥有多个实例。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-11
      • 2020-02-01
      相关资源
      最近更新 更多