iOS:iOS 4.3和5.0之间的不同addSubview行为

Krz*_*ube 29 iphone uiviewcontroller ipad ios ios5

虽然在iOS 4.3编码之前,我发现在将视图控制器的视图添加到另一个视图时[superview addSubView:controller.view],控制器实例将不会收到-viewWillAppear/viewDidAppear消息,比我在堆栈溢出中的某些线程中发现相同的问题.之后,我-viewWillAppear/-viewDidAppear根据需要手动调用.

但是,升级到之后iOS 5.0,UIView发生了一些活泼的行为.最后我发现在iOS 5中 [superview addSubView:controller.view],会-viewWillAppear/-viewDidAppear自动向控制器实例发送一条消息,加上我的手动调用,每次控制器动作其行为时都会有两条重复的消息.

我也发现了一个类似的问题:iOS 5:在解除iPad中的模态后没有调用-viewWillAppear

现在,问题是,在搜索苹果的文档之后,我没有找到关于这些问题的差异的明确文档.我甚至怀疑这是否是iOS 5.0中保证的视图生命周期行为.

有没有人解决类似问题或找到关于这些差异的一些指导.因为我想要运行我的应用程序4.x & 5.x iOS.

chr*_*ris 28

在iOS 4的,你不得不手动调用-viewWillAppear,-viewWillDisappear添加或删除您的视图层次视图时,等等.如果在窗口层次结构中添加或删除视图,则会在iOS 5中自动调用它们.幸运的是,iOS 5有一个方法UIViewController,您可以覆盖以将行为恢复为iOS 4的工作方式.只需将其添加到您的UIViewController:

-(BOOL)automaticallyForwardAppearanceAndRotationMethodsToChildViewControllers {
   return NO;
}
Run Code Online (Sandbox Code Playgroud)

这可能是最简单的解决方案,只要您支持iOS 4和iOS 5.一旦您放弃对iOS 4的支持,您可以考虑修改代码以在交换视图时使用更新的方法.

编辑2012年2月5日

显然,此功能需要使用该addChildViewController:方法将子视图控制器添加到主视图控制器中.iOS4中不存在此方法,因此您需要执行以下操作:

  if ([self respondsToSelector:@selector(addChildViewController:)] ) {
     [self addChildViewController:childViewController];
  }
Run Code Online (Sandbox Code Playgroud)

感谢所有纠正我的人.


hir*_*shi 9

这可能不是你想要的答案,但我有同样的问题.

在我的例子中,当我将视图控制器的视图添加到另一个视图控制器的视图作为子视图时,子视图仅在iOS 5.0而不是iOS 4.X中接收到viewWillAppear.

所以我添加了一个讨厌的条件.

[self.view addSubview:self.viewController.view];
if ([[[UIDevice currentDevice] systemVersion] compare:@"5.0"] == NSOrderedAscending) {
    [self.viewController viewWillAppear:animated];
}
Run Code Online (Sandbox Code Playgroud)

从iOS 5.0开始,Apple提供了一种实现自定义容器视图控制器的方法,如UINavigationController或UITabController.我认为这种变化会影响调用viewWillAppear的时间.

如果我们使用,这个问题可能是可以解决的-[UIViewController addChildViewController:].


小智 5

上面的答案略显不完整.我们假设您有2个视图控制器,ControllerA和ControllerB.

ControllerA.view已添加到窗口(它是父窗口),并且您想要将ControllerB.view添加为ControllerA的子视图.

如果不先添加ControllerB作为ControllerA的孩子,automaticallyForwardAppearanceAndRotationMethodsToChildViewControllers将被忽略,你将仍然iOS5的调用,这意味着你会打电话给您的视图控制器回调的两倍.

ControllerA中的示例:

- (BOOL)automaticallyForwardAppearanceAndRotationMethodsToChildViewControllers {
    return NO;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.controllerB = [[ControllerB alloc] initWithNibName:@"ControllerB" bundle:nil];

    [self.view addSubview:self.controllerB.view];
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    [self.controllerB viewWillAppear:animated];
}
Run Code Online (Sandbox Code Playgroud)

在ControllerW NSLogging中的viewWillAppear:

- (void)viewWillAppear:(BOOL)animated
{
    NSLog("@ControllerB will appear");
}
Run Code Online (Sandbox Code Playgroud)

这将导致iOS5仅显示两次NSLog消息.即你自动转发的外观和转动方法已经被忽略了.

为了解决这个问题,您需要将controllerB添加为控制器a的子节点.

回到ControllerA的课程:

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.controllerB = [[ControllerB alloc] initWithNibName:@"ControllerB" bundle:nil];
    if ([self respondsToSelector:@selector(addChildViewController:)])
        [self addChildViewController:self.controllerB];

    [self.view addSubview:self.controllerB.view];
}
Run Code Online (Sandbox Code Playgroud)

现在,这将在iOS4和iOS5中按预期工作,而无需考虑检查iOS版本字符串的可怕黑客,而是检查我们所使用的功能是否可用.

希望这可以帮助.