在实例化时使用代码更改故事板中的自定义类

时间:2012-08-30 01:52:59

标签: objective-c ios xcode

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

在故事板中,View Controller识别出“TabView”具有自定义类“TabColor”

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

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

此外,如果我使用nslog,结果是TabColor对象:

NSLog(@"%@", red)

预期:TabRed

实际:TabColor

2 个答案:

答案 0 :(得分:6)

TL; DR:

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

长版

故事板和类似的xib / nib文件实际上是编码对象的集合。当您在故事板中指定某个视图是UICustomColorViewController时,该对象将表示为该类的实例的序列化副本。然后加载故事板并调用instantiateViewControllerWithIdentifier:时,将创建故事板中指定的类的实例并将其返回给您。在这一点上,你被困在你给的对象上,但你并没有运气。

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

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

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

向viewcontroller添加委托属性:

@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];

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

答案 1 :(得分:3)

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

转换不会更改值,它只会更改编译器解释这些值的方式(并且当您使用类型代替另一个值时阻止它进行抱怨)。因此,将TabColor*转换为TabRed*告诉编译器假装您的第一个指针指向TabRed实例,但它不会将指针引用的对象转换为实例TabRed。

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

IB tab controller

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

IB custom class field

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

IB NIB Name setting

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

一开始可能会让人感到困惑,但要玩它。理解这将真正帮助您理解.xib文件(以及故事板)。当你是初学者时,它们看起来并不像它们看起来那么神奇,但一旦你得到它,它们看起来就会更酷。