如何在UIViewController中设置parentViewController?

时间:2009-09-07 21:39:23

标签: iphone cocoa-touch uiviewcontroller hierarchy parentviewcontroller

UIViewController的parentViewController属性是readonly,但我正在嵌套自定义视图控制器并希望使用此属性。

但是,由于它只是readonly,而我找不到设置此属性的其他方法,我的问题是: 我是如何设置它的?

显然,UINavigationController可以在-pushViewController中以某种方式设置属性,-presentModalViewController也可以这样设置,所以它必须是可能的。

我知道我可以添加自己的UIViewController属性,但我确信parentViewController原则上是正确的属性。

6 个答案:

答案 0 :(得分:11)

解决方案是:

   - (void)setParentController:(UIViewController*)parent{
 [self setValue:parent forKey:@"_parentViewController"];
    }

它不会导致链接器出现问题!

PS:不要使用“setParentViewController”作为方法名称,因为此方法存在于私有API中,Apple说: “应用程序中包含的非公共API是setParentViewController:。

如果您在源代码中使用与上述API相同的名称定义了一个方法,我们建议您更改方法名称,以便它不再与Apple的私有API发生冲突,以避免您的应用程序被标记为未来的提交。< / p>

请在下次更新时解决此问题......“

答案 1 :(得分:10)

我意识到这个问题是在iOS 5之前提出的,但是作为参考,你应该在想要嵌套UIViewControllers时使用addChildViewController。这也将自动设置parentViewController属性。

- (void)addChildViewController:(UIViewController *)childController NS_AVAILABLE_IOS(5_0);

您可以在Apple了解有关“创建自定义内容视图控制器”的更多信息。

答案 2 :(得分:2)

我试过Alex的建议为UIViewController制作一个类别,它在模拟器中工作,但不在我的手机上。这是类别

@interface UIViewController (parentSetter) 
-(void)setParentUIViewController:(UIViewController*)parent;
@end

@implementation UIViewController (parentSetter)
-(void)setParentUIViewController:(UIViewController*)parent
{
 _parentViewController = parent;
}
@end

它编译并正常工作,但请注意下划线成员有点偏。 这就是在编译3.0 SDK时导致链接器错误的原因。

我有一个包含2个子视图的容器视图,其中一个表是其中之一。该表需要父级,因此它可以与导航栏进行交互等。

我将使用此解决方案:

@interface AdoptedTableViewController : UITableViewController {
    UIViewController* surrogateParent;
}

-(UINavigationController*)navigationController;
@property (nonatomic, assign) IBOutlet UIViewController *surrogateParent;
@end

@implementation AdoptedTableViewController
@synthesize surrogateParent;

-(UINavigationController*)navigationController
{
    if( [super navigationController] )//self.navigationController ) 
    {
        return [super navigationController];
    }
    else
    {
        return surrogateParent.navigationController;
    }
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
}

我的所有表视图控制器现在都采用了TableViewControllers。他们需要父母的主要原因是他们可以将视图控制器推送到导航堆栈,因此导航控制器getter透明地处理。

如果parentViewController不是只读的话会很好,但是在我用_parentViewController的涉猎中我发现ViewController层次结构不仅仅是那个属性。我认为在这种关系中可能存在许多耦合和责任,苹果公司还没有为大众清理。例如,当我向上移动我无法修复的导航层次结构时,我注意到了一种奇怪的取消选择行为。也许UINavigation控制器反映了他们的顶级控制器的类,并且表现不同?

简而言之,它确实是只读的,没有干净或简单的解决方法。你只需要围绕它建设。

答案 3 :(得分:0)

但是,由于它只是readonly,而我找不到设置此属性的其他方法,我的问题是:我该如何设置它?

如果是readonly,则在未获得compiler error的情况下无法使用点表示法。

但是,您可以使用categoriesmodifyParentViewController课程添加自定义UIViewController方法。

即使属性是只读的,如果变量本身不是@protected,则变量本身可能是可修改的。如果是@protected,则对视图控制器进行子类化可以允许您选择修改变量。

答案 4 :(得分:0)

parentViewController用于NavigationViewControllers并呈现模态视图控制器,没有方法pushViewController或presentModalViewController就无法设置属性。 parentViewController是一个只读属性,只能由UIViewController类和UINavigationController类读取,这些类的子类将无权访问设置属性。

答案 5 :(得分:0)

看起来调用setParentViewController:方法有效。

[childViewController setParentViewController:self];

然而,这仍然会生成编译器警告。其中,IMO意味着不要这样做(我改为继承)。