6

我有一个标签栏控制器和一堆相同的标签。每个选项卡仅在功能上有所不同,但 UI 都相同。在情节提要中,我设计了一个选项卡的流程和 UI,并将其设置为基类。然后,当我创建选项卡时,我尝试在将它们添加到选项卡栏之前对它们进行类型转换,但它不起作用。

在情节提要中,标识为“TabView”的视图控制器具有自定义类“TabColor”

TabRed *red = (TabRed *)[storyboard instantiateViewControllerWithIdentifier:@"TabView"];
TabBlue *blue = (TabBlue *)[storyboard instantiateViewControllerWithIdentifier:@"TabView"];

然而,TabColor 中的 loadView 方法被调用,而不是 TabRed/TabBlue。

此外,如果我对其进行 nslog,则结果是 TabColor 对象:

NSLog(@"%@", red)

预期:TabRed

实际:TabColor

4

2 回答 2

6

tl;博士:

故事板和 xib 包含序列化对象的集合。在情节提要中指定一个类意味着您将在加载情节提要时获得该类的实例。获得您正在寻找的行为的一种方法是使用 cocoa/cocoa-touch 中常见的委托模式。

长版

故事板和类似的 xib/nib 文件实际上是一组编码对象。当您指定某个视图是情节提要中的 UICustomColorViewController 时,该对象表示为该类实例的序列化副本。当情节提要加载instantiateViewControllerWithIdentifier:并被调用时,情节提要中指定的类的实例将被创建并返回给您。在这一点上,你被给予的对象卡住了,但你并没有不走运。

由于看起来您想要做不同的事情,您可以构建您的视图控制器,以便该功能由使用委托的不同类处理。

创建一个协议来指定您希望在两个视图控制器之间有所不同的功能。

@protocol ThingDoerProtocol <NSObject>
    -(void) doThing;
@end

将委托属性添加到您的视图控制器:

@interface TabColor
...
@property (strong, nonatomic) thingDoerDelegate;

然后让你的新对象实现协议并做你想让他们做的事情。

@implementation RedTabDoer
    -(void) doThing {
         NSLog(@"RedTab");
    }
@end

@implementation BlueTabDoer
    -(void) doThing {
         NSLog(@"BlueTab");
    }
@end

然后在加载情节提要时创建并连接这些对象。

TabColor *red = [storyboard instantiateViewControllerWithIdentifier:@"TabView"];
red.thingDoerDelegate = [[RedTabDoer new] autorelease];

TabColor *blue = [storyboard instantiateViewControllerWithIdentifier:@"TabView"];
blue.thingDoerDelegate = [[BlueTabDoer new] autorelease];

然后,这应该允许您通过更改分配给控制器委托槽的对象类型来自定义视图控制器的功能。

于 2012-08-30T14:56:29.203 回答
3
TabRed *red = (TabRed *)[storyboard instantiateViewControllerWithIdentifier:@"TabView"];
TabBlue *blue = (TabBlue *)[storyboard instantiateViewControllerWithIdentifier:@"TabView"];

强制转换不会改变值,它只会改变编译器解释这些值的方式(并在你使用 type 代替另一个时阻止它抱怨)。因此,将 a 转换TabColor*为 a 会TabRed*告诉编译器假装您的第一个指针指向一个TabRed实例,但它不会将指针所指的对象变形为 TabRed 的实例。

正如 waltflanagan 所解释的,故事板和 .xib 文件包含实际对象,每个对象的类型在您创建文件时确定;你不能在运行时改变它。但是,您可以做的是让多个视图控制器中的每一个都加载相同的视图层次结构。您甚至不必编写任何代码来执行此操作。只需创建一个 .xib 文件,其中包含您的选项卡控制器和每个选项卡的视图控制器:

IB 选项卡控制器

请务必在 .xib 中适当地设置每个视图控制器的类型,以便为每个选项卡创建正确类型的视图控制器:

IB自定义类字段

为每个视图控制器设置“NIB 名称”字段以指定包含这些控制器将使用的视图层次结构的 .xib 文件。如果您为每个控制器指定相同的 .xib 文件,每个控制器将实例化自己的这些视图的副本:

IB NIB 名称设置

在视图控制器的公共超类中指定任何 IBOutlets,以便所有视图控制器具有相同的出口。您可以在通用 .xib 文件中将该超类指定为“文件所有者”的类型,以便 IB 知道哪些出口可用。文件的所有者实际上是加载 .xib 的对象的代理,因此当您的一个视图控制器(TabRed例如)加载公共视图 .xib 时,该控制器将是 .xib 中的视图所连接的那个控制器。TabBlue加载 .xib 时,该对象将是这些视图所连接的对象。

起初这可能看起来令人困惑,但请尝试一下。理解这一点将真正帮助您理解 .xib 文件(以及故事板)。当您是初学者时,它们的魔力要小得多,但是一旦您掌握了它们,它们就会看起来更酷。

于 2012-08-30T15:08:04.687 回答