【问题标题】:Subclass of UIViewController initialising itself from a .xib can't use UINavigationItem?从 .xib 初始化自身的 UIViewController 的子类不能使用 UINavigationItem?
【发布时间】:2011-01-15 23:05:12
【问题描述】:

我终于不得不放弃不懈地寻找这个问题的答案,因为我找不到以前问过这个问题的人!所以希望有人能提供一些见解。我将首先解释我能做什么,然后将其与我不知道该怎么做进行比较。

假设我有一个名为 RootViewController 的自定义 VC。它包含一个 MyViewController 类型的插座。我的 RootViewController 有一个 .xib,其中包含一个从 IB 调色板中拖出的通用 VC 对象,该对象被赋予 MyViewController 的类类型,我将右栏按钮项设置为名为“取消”的 UIBarButtonItem。 RootViewController 将其解档为 .xib,将插座连接到 MyViewController 对象,我将所述对象推送到按预期显示的导航堆栈上,我在导航栏上有一个视图和一个显示“取消”的按钮。

这种方法的问题是我希望 MyViewController 可以在任何可能想要创建 MyViewController 的对象中重复使用。因此,这意味着“文件的所有者”可以是任何对象。以前它是 RootViewController,但是如果另一个对象想要实例化一个 MyViewController 怎么办?文件所有者每次都会不同。我还希望它能够从一个非常独立的.xib 中完全初始化自己。基本上,我想这样做:

MyViewController *myVC = [[MyViewController alloc] init];

在 MyViewController 的实现中,我这样写:

- (id)init
{
    if ( self = [super initWithNibName:@"MyViewController" bundle:nil] )
    {
        // Initialisation
    }
}

这巧妙地隐藏了用于初始化 VC 的 .xib 的名称,利用了 IB 在配置控制器和视图时为我提供的所有优点,并且 MyViewController 始终是所有者,这意味着我也解决了文件所有者问题 -它适用于创建它的任何类型的类。

因此,为了实现这一点,我创建了一个 .xib,将文件的所有者设置为 MyViewController 类型,放入 UINavigationItem 并添加 UIBarButtonItem。我现在有一个结构与以前相同的 .xib,除了它不使用 IB 的通用 VC 对象作为单独的顶级对象,.xib 是 VC 定义,而不是包含 VC 定义的东西.

因此,鉴于 File's Owner 是 MyViewController 并且是 UIViewController 的子类(据说继承了您通过使用 IB 调色板中的 UIViewController 获得的所有内容),那么我应该继承它的超类的所有功能......除非它没有不。

当 .xib 未归档时,它不会连接 UINavigationItem。因此,当它被推送到导航堆栈时,不会显示任何条形按钮项。

UIViewControllers navigationItem 属性是只读的,因此不推荐在 iPhone OS 3.0 中为其创建 outlet。

那么,最后,nib 加载代码到底是如何设法将 IB 版本的 VC 对象连接到导航项的呢?为什么,即使我的对象 是 通过继承的 UIViewController,它不会为我的对象做呢?我完全无法理解这一点......

感谢您阅读本文!希望听听大师的意见

【问题讨论】:

    标签: iphone iphone-sdk-3.0 uiviewcontroller interface-builder


    【解决方案1】:

    只有 UINavigationController 设置 UIViewController 的 navigationItem 属性。做这样的事情:

    MyViewController *viewController = [[MyViewController alloc] init];
    [self.navigationController pushViewController:viewController animated:YES];
    [viewController release];
    

    假设你在一个已经有导航控制器的视图控制器中。推送之后,就可以从 MyViewController 内部访问 navigationItem。

    【讨论】:

    • 嗨,Sam,我回家后会仔细检查我所做的事情,但我几乎可以肯定我已经这样做了(在 NC 管理的 VC 中)。另外,您能否详细说明一下当您说 UINavigationController 设置 UIViewControllers 导航项时的意思?据我了解,导航项是 UIViewController 类的一个属性,当 VC 对象被推送到堆栈时,NC 会从 VC 请求 navigationItem 并在提供时显示它。这似乎是有道理的,因为在 IB 中您将导航项嵌入到 IB 的 VC 对象中。
    • Paul,如果我没记错的话,如果你制作了一个 UIViewController 并且不将它添加到 UINavigationController,那么它的 navigationItem 将为 nil。您是正确的,该属性是只读的。你不必设置它。如果系统没有设置它,则说明设置不正确。
    • 嗨,Sam,我再次查看了代码,可以验证我是否按照您的建议进行操作,但仍然无法正常工作。我花了很长时间编辑帖子以包含问题的图像和我的 .xib 的设置,只是发现我没有获得足够的积分来发布图像!啊!我怎么得到一些!?!
    【解决方案2】:

    好吧,我想我现在明白了。我想我会发布我自己问题的答案,因为我看到至少有其他人提出了类似的问题,并且似乎都指向相同的结论,所以我希望这对其他人有所帮助。

    本质上(这听起来很明显)UIViewController 不是代理对象!这并不是很明显,因为我们都习惯于这样的想法,即如果任何两个对象都从同一个基类继承,那么它们的实现是相同的,并且它们的行为方式完全相同(假设继承类中没有自定义)。但是 IB 对象的类型与您可以分配给这些对象的类属性不同。 它们不是两个 UIViewController 对象,因为它们的类属性是以这种方式设置的。

    在 IB 中简单地设置这些对象的 class 属性并不意味着这些对象现在是 UIViewController 对象。视图控制器对象仍然是视图控制器对象,代理对象仍然是代理对象。对 IB 来说,它们都是非常不同的野兽,只是恰好具有相同的类属性。

    只需查看 .xib,您就会发现您的 IB 视图控制器对象已按如下方式归档:

    <object class="IBUIViewController" id="...">
        ...
    </object>
    

    并且代理对象(设置为 UIViewController 的子类)是这样归档的:

    <object class="IBProxyObject" id="...">
        ...
    </object>
    

    正如您所看到的,它们都是非常不同的类型,一种是 IBUIViewController,另一种是 IBProxyObject - 然后它开始变得有意义 - 您不能将 VC 控制器属性强加于 IBProxyObject 类型的对象。

    值得注意的是,类类型是IBUIViewController 对象,而不仅仅是UIViewController 对象。这是否只是一个命名约定我不知道,但它也可能意味着 IB 的视图控制器对象包装了实例化的 VC 对象,或者是它的工厂对象。例如,您可以在 IB 的视图控制器对象中设置“Resize View From NIB”属性 - 但我在 UIViewController 参考文档中找不到等效的属性或方法。

    因此,总而言之,如果您尝试以编程方式实例化一个对象,而不是使用 IB 对象的出口,请准备好实现一些 IB 版本原本会为您提供的初始化...

    【讨论】:

      猜你喜欢
      • 2016-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-14
      • 2015-02-04
      • 2015-09-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多