【问题标题】:How to set parentViewController in UIViewController?如何在 UIViewController 中设置 parentViewController?
【发布时间】:2010-11-26 08:05:37
【问题描述】:

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

但是,由于它是只读的,并且我没有找到其他方法来设置此属性,所以我的问题是:如何设置它?

很明显,UINavigationController可以在-pushViewController中以某种方式设置属性,-presentModalViewController也可以,所以一定可以。

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

【问题讨论】:

  • 我认为无论谁对这个线程中的每个答案都投了反对票,都可以给出一个理由:)
  • 不是我,但我怀疑他们不同意使用私有 API,并且投票否决使用私有 API 的建议似乎在 SO 上很常见。也许他们是苹果痣。

标签: iphone cocoa-touch uiviewcontroller hierarchy parentviewcontroller


【解决方案1】:

解决办法是:

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

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

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

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

请在下次更新中解决此问题..."

【讨论】:

  • 这不会导致 App Store 被拒绝吗?这解决了我的一些模态表示问题,但是很吓人。
【解决方案2】:

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

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

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

【讨论】:

  • 这对我有用,在子视图控制器上设置 parentViewController 属性。不知道为什么它不是被接受的答案。
【解决方案3】:

我尝试了 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 层次结构不仅仅是那个属性。我认为在这种关系中可能存在很多耦合和责任,Apple 还没有为大众清理足够的东西。例如,在向上移动导航层次结构时,我注意到一个奇怪的取消选择行为,我无法修复。也许 UINavigation 控制器反映了它们的顶级控制器的类并且行为不同?

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

【讨论】:

    【解决方案4】:

    但是,由于它是只读的,我没有找到其他方法来设置这个属性,我的问题是:我该如何设置它?

    如果是readonly,你不能在没有compiler error的情况下使用点符号。

    但是,您可以使用categories 将自定义modifyParentViewController 方法添加到UIViewController 类。

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

    【讨论】:

    • 这样做对我来说有点太脏了,但我想如果我坚持使用 parentViewController,这几乎是唯一可能的方法。
      我将使用自定义 UIViewController属性。
    • 父级上的addChildViewController是应该怎么做的。
    【解决方案5】:

    parentViewController 用于 NavigationViewControllers 和呈现模式视图控制器,没有方法 pushViewController 或 presentModalViewController 就无法设置属性。 parentViewController 是只读属性,只能被 UIViewController 类和 UINavigationController 类读取,它们的子类将无权设置该属性。

    【讨论】:

      【解决方案6】:

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

      [childViewController setParentViewController:self];
      

      但是这仍然会产生编译器警告。哪个,IMO,意味着不要这样做(我改为子类化)。

      【讨论】:

        猜你喜欢
        • 2019-04-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-04-26
        • 2019-05-28
        • 1970-01-01
        • 2013-09-11
        • 1970-01-01
        相关资源
        最近更新 更多