我正在尝试做一些事情:
某些对象中的UITableVIewController *viewController;
[someObjectB setupView: viewController];
-(void) setupView:(UIViewController*)view
{
if the pointer passed in is of type UITableViewController then ...
say, for instance with: [[view class] isKindOfClass [UITableViewController class]]
or: [view isKindOfClass [UITableViewController class]]
}
但是,我有两个问题: 首先,参数作为UIViewController进入B中的方法,UIViewController是UITableView的超类(我正在这样做,因为这个方法也会配置其他类型的视图控制器)。所以我想知道,如果我将UITableViewController传递给UIViewController类型的方法参数,isKindOfClass仍然可以进行动态绑定吗?也就是说,运行时检查内容的类型,而不管指针的静态类型是什么?
其次,请注意我在将对象A传递给B之前没有初始化它。我实际上希望B初始化它。但随后购买问题变成了,如何在未初始化的指针上测试静态指针类型?也就是说,在B里面:[view isKindOfClass [UITableViewController class]]给了我一个BAD_EXEC。我猜,因为我显然试图访问jul指针。那么还有一种方法可以根据指针静态类型声明进行测试吗?
让我用更具体的术语重新解释这个问题的一部分:我希望obj B创建一个UITableViewController类型的变量,将它传递给A并让A知道它已经被赋予了一个指向UITableViewController的指针,因此它实际上可以初始化这个指向UITableViewController的特定子类的指针,然后obj B将现在初始化的对象传递给其他对象。
我想要这样做的理由是以下场景: 我有一个基于navigationController的应用程序。它有一个带按钮的根控制器,根据按下的按钮,根控制器实例化并推送数据库的不同表的表控制器,反过来,当单击这些表的一行时,表实例化并推送详细视图控制器。
到目前为止一直很好,但由于项目的性质,我想保持整个navigationcontroller实例化 - 推送链不可知的事实是有一个数据库,并且表和详细视图控制器实际上是特定的子类分别是UITableViewController和UIViewController。
这意味着流程将是:
1-单击,根控制器将通用UIViewController传递给我的自定义主控制器。
2-这个主控制器意识到已经传递了一个通用表,将它初始化为我定义的特定子类,并做了一些事情来为它提供来自sql数据库的数据。
3 - 根控制器,不关心通用UIViewController是否是一个表,甚至不关心UIViewController的子类,只是将它推送到navigationController。
同样,我的想法是,我不需要在根控制器中包含表子类的标头。只有自定义主控制器知道这些。
所以,在一天结束时,我看到这样做的方式是能够确定传递的指针的类型是什么,无论这个指针是否为nil,指向垃圾或指向一个实际对象。含义:
UIVIewController * a - >静态类型声明,在编译时确定。
a = [UIVIewController alloc的一些子类] init]; - >指针内容的动态类型,在运行时确定,可能是通过激活记录跟踪链接。类似于C ++中的“虚拟”
答案 0 :(得分:2)
Objective-C是一种按值传递的语言,就像C一样。您不能使用您在那里的代码初始化对象A中的viewController
。初始化它,将其地址传递给setupView:
,然后根据需要进行初始化:
UITableVIewController *viewController = nil;
[someObjectB setupView:&viewController];
和
-(void)setupView:(UIViewController**)view
{
if (*view == nil)
// initialize it - *view = [[blah alloc] init] or whatever
else
...
}
答案 1 :(得分:2)
在回答第一个问题时,是 - Objective C将在运行时(动态)确定对象的类类型。在回答第二个问题时,任何调度到nil对象的方法调用都会被忽略,因此所有类检查都不会真正起作用。但是你不应该得到BAD_EXEC,除非你:
*编辑*
添加了一个可以获得BAD_EXEC的场景,另外,请参阅下面的链接,了解测试类相等性时的几个问题,特别是使用isKindOfClass
方法。
In Objective-C, what is the equivalent of Java's "instanceof" keyword?
答案 2 :(得分:2)
正如其他人所指出的那样,你所要求的是不可能的。将变量传递给方法时,它只发送值,而不是类型。此外,运行时不了解方法中变量的类型。任何变量类型处理都由编译器完成。运行时只能知道变量所持有的对象的类。
作为替代方案,如果您可以更改方法的签名,则可以添加一个参数来指示要创建的对象的类型。调用方法仍然不需要知道对象的确切类型,只需知道它是否是表视图控制器。这是一个使用枚举来保存不同类型的示例。
// header
enum ViewControllerType {
ViewControllerNormal = 0,
ViewControllerTableView
};
- (void)setupView:(UIViewController **)view ofType:(enum ViewControllerType)type;
// implementation
- (void)setupView:(UIViewController **)view ofType:(enum ViewControllerType)type {
if(!view) {
NSLog(@"setupView:ofType: received nil pointer");
return;
}
switch(type) {
case ViewControllerNormal:
// create normal UIViewController type
break;
case ViewControllerTableView:
// create UITableViewController type
break;
default:
NSLog(@"setupView:ofType: received unknown type: %i",type);
return;
}
}
用过:
UIViewController *view;
[creatorObject setupView:&view ofType:ViewControllerNormal];
// or
UITableViewController *tableView;
[creatorObject setupView:&tableView ofType:ViewControllerTableView];