2008-09-25 111 views
104

我读过有关有问题的人viewWillAppear无数的帖子,当你不创建视图层次只是权。我的问题是我无法弄清楚这意味着什么。iPhone viewWillAppear中没有发射

如果我创建了一个RootViewController并且在该控制器上调用addSubView,我期望将添加的视图连接到viewWillAppear事件。

有没有人有一个复杂的编程视图层次结构的例子,成功地在每个级别接收viewWillAppear事件?

苹果的文档状态:

警告:如果属于视图控制器视图直接添加到一个视图层次结构,视图控制器将不会收到此消息。如果向视图层次结构中插入或添加视图,并且它具有视图控制器,则应直接将关联的视图控制器发送此消息。无法发送视图控制器此消息将阻止显示任何关联的动画。

问题是,他们没有描述如何做到这一点。 “直接”是什么意思?你如何“间接”添加视图?

我对Cocoa和iPhone相当陌生,所以如果除了基本的Hello World废话之外还有Apple的有用示例,那将会很不错。

+0

直到我意识到我是错误理解用途的UIViewController子类通常我有这个问题。看看这个问题。 http://stackoverflow.com/questions/5691226/am-i-abusing-uiviewcontroller-subclassing/5691708#comment-6507338 – averydev 2011-04-17 23:26:47

+7

请当心!不再适用于iOS 5!调用viewWillAppear和viewDidAppear自动调用 – 2011-11-10 17:23:51

回答

5

我一直在使用导航控制器。当我想要么下降到数据的另一级或显示我的自定义视图我使用以下命令:

[self.navigationController pushViewController:<view> animated:<BOOL>]; 

当我这样做,我得到的viewWillAppear功能火灾。我认为这是“间接的”,因为我自己并没有调用实际的addSubView方法。我不知道这是否适用于您的应用程序,因为我无法分辨您是否使用导航控制器,但它可能会提供线索。

27

我遇到了同样的问题。在将其添加为子视图之前,只需将viewWillAppear消息发送给您的视图控制器即可。 (有它告诉视图控制器,如果它被动画显示或不一个BOOL参数。)

[myViewController viewWillAppear:NO]; 

看RootViewController.m在节拍​​器例子。

(其实,我发现苹果的示例项目很大还有很多比的HelloWorld多;)

+3

实际上,在将其添加到子视图后,您应该调用viewWillAppear。否则,IBOutlets/IBActions将不会连线。 – 4thSpace 2009-06-17 15:37:11

+2

是的,事后。从XIB创建子视图,viewWillAppear没有被调用。自己调用它,一切正常。 – JOM 2010-02-16 07:03:13

+0

谢谢!这对我来说就是这样。我通过`[scrollView addSubview:controller.view];`手动添加子视图。我加了一行`[controller viewWillAppear:NO];`然后瞧!像魅力一样工作。 – 2010-05-09 18:43:04

1

我不是这个100%肯定,但我认为,添加视图到视图层次直接意味着调用-addSubview:在视图控制器的视图上(例如,[viewController.view addSubview:anotherViewController.view]),而不是将新的视图控制器推到导航控制器的堆栈上。

51

如果您使用导航控制器并设置其委托,则不会调用{Will,Did} {Appear,Disappear}方法。

您需要使用导航控制器委托方法代替:

navigationController:willShowViewController:animated: 
navigationController:didShowViewController:animated: 
1

我认为增加一个子视图并不一定意味着该视图会出现,所以没有对类的方法自动呼叫它会

7

我刚刚有同样的问题。在我的应用程序中,我有2个导航控制器,并推动相同的视图控制器在他们每个工作在一个案件,而不是在另一个。我的意思是,当在第一个UINavigationController中推送完全相同的视图控制器时,viewWillAppear被调用,但在第二个导航控制器中被推入时不会被调用。

然后,我遇到了这个职位UINavigationController should call viewWillAppear/viewWillDisappear methods

,并意识到,我的第二个导航控制器做了重新定义viewWillAppear。筛选的代码表明,我没有打电话

[super viewWillAppear:animated]; 

我添加它和它的工作!

文档说:

如果重写此方法,您必须在您执行某些时候调用超。

1

我认为他们的意思是“直接”,就是通过与xcode“导航应用程序”模板相同的方式将事物挂钩,它将UINavigationController设置为应用程序UIWindow的唯一子视图。

使用该模板是我能够在UINavigationController中的这些控制器的推/拉弹出时获得在对象ViewControllers上调用的Will/Did/Appear/Disappear方法的唯一方法。这里的答案中没有其他解决方案适用于我,包括在RootController中实现它们并将它们传递给(子)NavigationController。在显示/隐藏顶层VC,我的“登录”和navigationVCs,而不是导航控制器中的子VC之后,这些功能(将/出现/消失)仅在我的RootController中调用,所以我没有机会“通过他们”到导航VC。

我最终使用UINavigationController的代理功能来查找需要后续功能的特定转换,并且这种转换能够正常工作,但它需要更多的工作才能同时获得消失和显示功能“模拟”。

另外这是一个原则性的问题,在今天将这个问题撞上这个问题几个小时后让它工作。任何使用自定义RootController和子导航VC的工作代码片段将非常感谢。

1

如果这有助于任何人。我有一个类似的问题,我的ViewWillAppear未在UITableViewController上发射。经过大量玩耍后,我意识到问题在于控制我的UITableViewUINavigationController不在根视图上。一旦我解决这个问题,它现在像一个冠军。

3

通过调用[view addSubview:subview]“直接”添加视图。 通过交换子视图的选项卡栏或导航栏等方法“间接”添加视图。

任何时候你打电话[view addSubview:subviewController.view],你应该打电话[subviewController viewWillAppear:NO](或YES作为你的情况)。

当我在游戏中为子屏幕实现我自己的自定义根视图管理系统时,我遇到了这个问题。手动添加呼叫viewWillAppear治好了我的问题。

1
[self.navigationController setDelegate:self]; 

将委托设置为根视图控制器。

3

由于没有答案被接受,人们(像我一样)降落在这里,我给我的变化。虽然我不确定这是最初的问题。当导航控制器添加作为一个子视图到另一个视图,你必须自己调用viewWillAppear中/ Dissappear等方法是这样的:

- (void) viewWillAppear:(BOOL)animated 
{ 
    [super viewWillAppear:animated]; 

    [subNavCntlr viewWillAppear:animated]; 
} 

- (void) viewWillDisappear:(BOOL)animated 
{ 
    [super viewWillDisappear:animated]; 

    [subNavCntlr viewWillDisappear:animated]; 
} 

只是为了让这个例子完整。这段代码出现在我的ViewController中,我创建并将导航控制器添加到我放置在视图中的视图中。

- (void)viewDidLoad { 

    // This is the root View Controller 
    rootTable *rootTableController = [[rootTable alloc] 
       initWithStyle:UITableViewStyleGrouped]; 

    subNavCntlr = [[UINavigationController alloc] 
        initWithRootViewController:rootTableController]; 

    [rootTableController release]; 

    subNavCntlr.view.frame = subNavContainer.bounds; 

    [subNavContainer addSubview:subNavCntlr.view]; 

    [super viewDidLoad]; 
} 

的.H看起来像这样

@interface navTestViewController : UIViewController <UINavigationControllerDelegate> { 
    IBOutlet UIView *subNavContainer; 
    UINavigationController *subNavCntlr; 
} 

@end 

在笔尖文件I具有视图和该视图下面我有标签的图像和其中i把控制器中的容器(另一个视图)这里是它的外观。我必须争取一些东西,因为这是为客户做的工作。

alt text

16

我终于找到了解决这个的作品!

UINavigationControllerDelegate

我认为它的要点是你的导航控制的委托设置到ViewController它在,并实现UINavigationControllerDelegate和它的两个方法。辉煌!我很激动,我终于找到了解决方案!

4

首先,如Apple文档中所述,选项卡栏应位于根级别,即添加到窗口。这是正确行为的关键。

其次,你可以使用UITabBarDelegate/UINavigationBarDelegate转发手动的通知,但我发现,要得到从整体层次要求正常工作,我所要做的就是手动调用

[tabBarController viewWillAppear:NO]; 
[tabBarController viewDidAppear:NO]; 

[navBarController viewWillAppear:NO]; 
[navBarController viewDidAppear:NO]; 

..只是一旦相应的控制器上设置的视图控制器之前(分配后右)。从此,它在其子视图控制器上正确调用了这些方法。

我的层次结构是这样的:

window 
    UITabBarController (subclass of) 
     UIViewController (subclass of) // <-- manually calls [navController viewWill/DidAppear 
      UINavigationController (subclass of) 
       UIViewController (subclass of) // <-- still receives viewWill/Did..etc all the way down from a tab switch at the top of the chain without needing to use ANY delegate methods 

只需调用标签/导航控制器在第一时间确保所有事件正确转发上提到的方法。它阻止了我需要从UINavigationBarDelegate/UITabBarControllerDelegate方法手动调用它们。

旁注: 奇怪的是,当它没有工作,私有方法

- (void)transitionFromViewController:(UIViewController*)aFromViewController toViewController:(UIViewController*)aToViewController 

..你可以从调用堆栈上看到一个工作的实施,通常调用viewWill/Did..的方法,但并没有到我执行了上述(即使它被称为)。

我认为这是非常重要的UITabBarController是在窗口级别,但文件似乎支持这一点。

希望明确(ish),很乐意回答更多问题。

-3

您应该在任何时候只有1个UIViewController处于活动状态。任何你想操作的子视图都应该是 - subVIEWS - 即UIView。

我使用一种简单的技术来管理我的视图层次结构,并且由于我以这种方式开始做事,所以还没有遇到问题。有2个关键点:

  • 单一的UIViewController应该用来管理“屏幕的价值”您的应用程序的
  • 使用UINavigationController的改变观点

这是什么意思是“一个屏幕的价值“?它的目的有点模糊,但通常它是应用程序的功能或部分。如果你有几个屏幕具有相同的背景图像,但不同的叠加/弹出等,应该是1视图控制器和几个子视图。你永远不应该发现自己使用2个视图控制器。请注意,如果您希望在多个视图控制器中显示屏幕的某些区域,您仍然可以在一个视图控制器中实例化UIView,并将其添加为另一个视图控制器的子视图。

至于UINavigationController - 这是你最好的朋友!关闭导航栏并将动画指定为NO,并且您可以根据需要切换屏幕。如果视图控制器处于层次结构中,则可以推送和弹出视图控制器,也可以准备视图控制器数组(包括包含单个VC的数组),并使用setViewControllers将其设置为视图堆栈。这使您可以完全自由地改变VC,同时获得苹果预期模式中的所有优势,并让所有事件正确启动。

这是我做的每一次当我启动的应用程序:从基于窗口的应用程序

  • 开始
  • 添加一个UINavigationController作为窗口的RootViewController的
  • 添加任何我想我的第一次的UIViewController来作为nav的根视图控制器 控制器

(注意从基于窗口的开始只是个人偏好 - 我喜欢自己构建东西,所以我确切知道它们是如何构建的。它应该正常工作的罚款基于视图的模板)

所有事件火灾和基本生活是美好的。然后,您可以将所有时间都花在编写应用程序的重要部分,而不是尝试手动将视图层次结构变形为形状。

-1

我不知道这是我解决了同样的问题。
在某些情况下,方法不能与正常的方式执行的,如“[自methodOne]”。

尝试

- (void)viewWillAppear:(BOOL)animated 
{ 
    [self performSelector:@selector(methodOne) 
      withObject:nil afterDelay:0]; 
} 
2

我使用push和pop视图控制器验证码:

推:

[self.navigationController pushViewController:detaiViewController animated:YES]; 
[detailNewsViewController viewWillAppear:YES]; 

流行:

[[self.navigationController popViewControllerAnimated:YES] viewWillAppear:YES]; 

..它的工作原理对于我来说足够了。

1

我只是有这个问题,我和我花了整整3小时(其中谷歌搜索2)进行修复。

原来帮忙的是简单的从设备/模拟器中删除应用程序,清理并再次运行

希望帮助

2

一个非常常见的错误如下。 你有一种观点认为,UIView* a,和一个又一个,UIView* b。 您将b添加到a作为子视图。 如果您尝试在b中调用viewWillAppear,它将永远不会被解雇,因为它是子视图

3

正确的方法是使用UIViewController containment api。

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    // Do any additional setup after loading the view. 
    UIViewController *viewController = ...; 
    [self addChildViewController:viewController]; 
    [self.view addSubview:viewController.view]; 
    [viewController didMoveToParentViewController:self]; 
}