Iphone iOS:iOS 4.3和5.0之间的addSubview行为不同
在之前的iOS 4.3中进行编码时,我发现当使用Iphone iOS:iOS 4.3和5.0之间的addSubview行为不同,iphone,ios,ipad,uiviewcontroller,ios5,Iphone,Ios,Ipad,Uiviewcontroller,Ios5,在之前的iOS 4.3中进行编码时,我发现当使用[superview addSubView:controller.view]将视图控制器的视图添加到另一个视图时,控制器实例将不会收到-viewwilldisease/viewdidisease消息,而我在堆栈溢出的某些线程中发现了相同的问题。之后,我会根据需要手动调用-viewwillbeen/-viewdidebeen 但是,升级到iOS 5.0后,出现了一些轻浮的UIView行为。最后,我发现在iOS 5中,[superview addSub
[superview addSubView:controller.view]
将视图控制器的视图添加到另一个视图时,控制器实例将不会收到-viewwilldisease/viewdidisease
消息,而我在堆栈溢出的某些线程中发现了相同的问题。之后,我会根据需要手动调用-viewwillbeen/-viewdidebeen
但是,升级到iOS 5.0后,出现了一些轻浮的UIView行为。最后,我发现在iOS 5中,[superview addSubView:controller.view]
会自动向控制器实例发送一条-viewwillbeen/-viewdidebeen
消息,再加上我的手动调用,每次控制器操作其行为时都会有两条重复消息
我还发现了一个类似的问题:
现在的问题是,在搜索苹果的文档后,我没有找到任何关于这些问题的diff的明确文档。我甚至想知道这是否是iOS 5.0中保证的视图生命周期行为
是否有人解决了类似的问题或找到了一些关于这些差异的指导方针。因为我想在
4.x和5.x iOS中运行我的应用程序
通过这种方法,你知道你使用的是哪个操作系统,如果小于5.0或其他操作系统,则设置条件
[[UIDevice currentDevice]systemVersion]这可能不是您想要的答案,但我遇到了同样的问题 在我的例子中,当我将一个视图控制器的视图作为子视图添加到另一个视图控制器的视图中时,收到的子视图视图将仅显示在iOS 5.0而不是iOS 4.X中 所以我增加了一个恶劣的条件
[self.view addSubview:self.viewController.view];
if ([[[UIDevice currentDevice] systemVersion] compare:@"5.0"] == NSOrderedAscending) {
[self.viewController viewWillAppear:animated];
}
从iOS 5.0。我认为此更改会影响调用viewwillbeen的时间
如果我们使用
-[UIViewController addChildViewController:
这是iOS5行为:,这个问题可能会得到解决 视图将出现,视图显示。。。在iOS5的addSubView:之后自动执行
因此,对于iOS5,无需手动执行这些方法,因为iOS需要查看{Will,Did}出现,
查看{Will,Did}消失
是查看控制器上的函数,而不是视图。这些函数由SDK提供的视图控制器调用,这些视图控制器应管理其他视图控制器,例如UITabBarController
,UINavigationBarController
如果您自己管理子视图控制器,则必须显式地调用这些子视图控制器(并且按照正确的顺序调用-尽管您应该有很好的理由这样做)。模态视图在取消模态视图时没有得到这些调用仅仅是因为没有人调用它。将根视图控制器封装在
UINavigationController
中(如果愿意,隐藏导航栏),然后打开模式视图控制器。当它被撤销或弹出时,视图将出现
将被调用 在iOS 4中,当从视图层次结构中添加或删除视图时,您必须手动调用-viewwillbeen
,-viewwillbeside
,等等。如果视图正在从窗口层次结构中添加或删除,则在iOS 5中会自动调用这些视图。幸运的是,iOS 5在UIViewController
中有一个方法,您可以覆盖该方法,将行为恢复到iOS 4的工作方式。只需将此添加到您的UIViewController
:
-(BOOL)automaticallyForwardAppearanceAndRotationMethodsToChildViewControllers {
return NO;
}
只要您同时支持iOS 4和iOS 5,这可能是最简单的解决方案。一旦你放弃了对iOS 4的支持,你可能会考虑修改你的代码来使用新的方法来交换视图。
编辑2012年2月5日
显然,此函数要求使用addChildViewController:
方法将子视图控制器添加到主视图控制器。iOS4中不存在此方法,因此需要执行以下操作:
if ([self respondsToSelector:@selector(addChildViewController:)] ) {
[self addChildViewController:childViewController];
}
谢谢大家纠正了我的错误。上面的答案有点不完整。 假设您有两个视图控制器,ControllerA和ControllerB ControllerA.view已添加到窗口(它是父视图),您希望将ControllerB.view添加为ControllerA的子视图
如果不首先将ControllerB添加为ControllerA的子级,则AutomaticallyForwardAppearanceAndRotationMethodToChildViewController将被忽略,并且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];
}
在ControllerB中,将显示登录视图:
- (void)viewWillAppear:(BOOL)animated
{
NSLog("@ControllerB will appear");
}
这将导致iOS5仅显示该NSLog消息两次。i、 e.您的自动外观和定位方法已被忽略 为了解决这个问题,您需要将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];
}
这在iOS4和iOS5中都能像预期的那样工作,而不必求助于检查iOS版本字符串这一可怕的黑客手段,而是检查我们所追求的函数是否可用
希望这有帮助。在查看了所有证据后,我认为最好不要对受此ios 4/ios 5错误影响的视图使用viewDidAppear等。而是创建一个自定义类(比如viewdiappearcustom)并自己调用它。这样你就可以保证苹果不会再改变sdk,把你搞得一团糟。这里有一个关于这个问题的博客:
我知道这种方法,请帮忙。我想知道更多关于这些区别的信息。我不认为这和操作系统版本有任何关系。API保持不变。关于何时调用viewWillApear/English,有固定的规则。谢谢,修复了ios4上的问题,但是在ios5上调用了两次viewwillbeen(一次来自我输入的手动调用),不知道为什么。Richy。。这很奇怪,因为这个方法在iOS4中被忽略,只在iOS5中调用。whalec:我不确定我是否同意你的编辑,所以可能是最好的
- (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];
}