不同UIViewController的调用方法

时间:2014-08-06 16:46:50

标签: ios objective-c uiviewcontroller

我正在制作主细节应用程序,我有动态Detail ViewController。细节ViewController已更改。

但是在每个Detail ViewController中我都有一个常用的方法updateInfo我想调用那个方法

这是我的代码

UINavigationController *nav=[self.splitViewController.viewControllers objectAtIndex:1];
 UIViewController *controller=[nav.viewControllers objectAtIndex:0];
 [controller updateLastInfo];

但它给了我错误没有找到方法。

如果我使用UIViewController名称,它将起作用。

  HomeViewController *controller=(HomeViewController)[nav.viewControllers objectAtIndex:0];
     [controller updateLastInfo];

但我不想做上面的事情

我试图解释一下。请帮忙

3 个答案:

答案 0 :(得分:1)

您可以使用id

 UINavigationController *nav=[self.splitViewController.viewControllers objectAtIndex:1];
    id controller=[nav.viewControllers objectAtIndex:0];
    [controller updateLastInfo];

答案 1 :(得分:1)

您可以创建UIViewController的子类并创建一个基本DetailViewController类,其中包含详细视图控制器的常用功能。然后,您将使所有详细视图控制器成为子类DetailViewController而不是UIViewController。这将是一种安全的方法,并且还允许您在特定详细信息视图控制器中为updateInfo方法添加额外功能。


如果您想要一种不安全的方法,可以使控制器对象的类型为id。我不会建议这种方法,因为它依赖于您对代码的个人知识。如果其他人(或者你自己在路上)将它设置为没有该方法的视图控制器,代码仍将尝试运行并将崩溃。

答案 2 :(得分:1)

UIViewController没有一个名为updateInfo的方法,因此当您尝试将该消息发送到只知道指向的指针时编译器会抱怨UIViewController的一个实例。当您使用类名时,如下所示:

HomeViewController *controller=(HomeViewController)[nav.viewControllers objectAtIndex:0];

您正在向编译器提供更多信息,使用类型转换来告诉它"嘿,不要担心,我肯定知道我回来的对象是一个HomeViewController。由于您似乎有几种类型的视图控制器都具有此方法,因此最好的做法是在协议中声明updateInfo方法,然后让每个UIViewController子类实现该协议。因此,您的协议声明将位于头文件中,可能如下所示:

@protocol SomeProtocol

- (void)updateInfo

@end

并且每个具有-updateInfo方法的类只需要声明它采用协议:

@interface HomeViewController <SomeProtocol>
//...
@end

然后确保您的班级实施中有-updateInfo

@implementation HomeViewController

- (void)updateInfo {
    //...
}

//...
@end

然后,在您的代码中,您可以使用-conformsToProtocol:检查对象是否符合协议:

if ([controller conformsToProtocol:@protocol(SomeProtocol)]) {
    UIViewController<SomeProtocol> *c = (UIViewController<SomeProtocol>*)controller;
    [c updateInfo];
}

或者在调用之前检查对象是否响应选择器:

if ([controller respondsToSelector:@selector(updateInfo)]) {
    [controller performSelector(updateInfo)];
}

您收到的其他答案(使用id或创建公共基类)也很好,但为了安全起见,请确保在调用方法之前进行一些检查。例如,您可以使用-isKindOfClass来确保您获得的视图控制器实际上是您的公共基类的实例,并且您可以使用上面的-respondsToSelector:来检查{{1}指向实现id的对象。