iPhone viewWillAppear没有开火

iphone ios cocoa-touch

96093 观看

25回复

579 作者的声誉

我读过许多有关职位有问题的人viewWillAppear,当你不创建视图层次只是权利。我的问题是我无法弄清楚这意味着什么。

如果我在该控制器上创建RootViewController并调用addSubView,我希望添加的视图可以连接到viewWillAppear事件。

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

Apple的Docs声明:

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

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

我对Cocoa和iPhone相当新,所以如果除了基本的Hello World垃圾之外还有来自Apple的有用示例,那将会很不错。

作者: chzk 的来源 发布者: 2008 年 9 月 25 日

回应 (25)


5

3246 作者的声誉

我一直在使用导航控制器。当我想要下降到另一个级别的数据或显示我的自定义视图时,我使用以下内容:

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

当我这样做时,我确实得到了viewWillAppear解雇的功能。我认为这有资格作为“间接”,因为我addSubView自己并没有调用实际的方法。我不知道这是否100%适用于您的应用程序,因为我无法判断您是否使用导航控制器,但它可能会提供线索。

作者: Josh Gagnon 发布者: 25.09.2008 07:24

29

19945 作者的声誉

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

[myViewController viewWillAppear:NO];

查看Metronome示例中的RootViewController.m。

(我实际上发现Apple的示例项目很棒。比HelloWorld更多;)

作者: lajos 发布者: 28.09.2008 01:20

1

34215 作者的声誉

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

作者: Martin Gordon 发布者: 07.10.2008 03:51

53

8171 作者的声誉

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

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

navigationController:willShowViewController:animated:
navigationController:didShowViewController:animated:
作者: mmalc 发布者: 17.10.2008 04:35

1

0 作者的声誉

我认为添加子视图并不一定意味着视图会出现,所以没有自动调用类的方法它会

作者: winston 发布者: 25.05.2009 06:05

8

111 作者的声誉

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

然后我遇到这个帖子UINavigationController应该调用viewWillAppear / viewWillDisappear方法

并意识到我的第二个导航控制器确实重新定义了viewWillAppear。筛选代码显示我没有打电话

[super viewWillAppear:animated];

我加了它,它工作了!

文件说:

如果重写此方法,则必须在实现中的某个时刻调用super。

作者: Antoine 发布者: 13.01.2010 02:46

1

17117 作者的声誉

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

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

我最终使用UINavigationController的委托功能来查找在我的应用程序中需要后续功能的特定转换,这是有效的,但它需要更多的工作才能使消失和显示功能“模拟”。

在今天几个小时之后对这个问题猛烈抨击之后,让它开始工作也是一个原则问题。任何使用自定义RootController和子导航VC的工作代码片段都将非常受欢迎。

作者: Bogatyr 发布者: 15.06.2010 03:50

1

11 作者的声誉

如果这有助于任何人。我有一个类似的问题,我ViewWillAppear没有开火UITableViewController。经过大量的游戏,我意识到问题UINavigationController在于控制我UITableView的不是根视图。一旦我解决了这个问题,它现在就像一个冠军。

作者: Andrew 发布者: 19.11.2010 08:18

3

5769 作者的声誉

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

你打电话的时候[view addSubview:subviewController.view],你应该打电话[subviewController viewWillAppear:NO](或者根据你的情况而定)。

当我为游戏中的子屏幕实现自己的自定义根视图管理系统时,我遇到了这个问题。手动添加对viewWillAppear的调用解决了我的问题。

作者: AndrewS 发布者: 22.11.2010 03:21

1

4245 作者的声誉

[self.navigationController setDelegate:self];

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

作者: Gaurav 发布者: 23.11.2010 01:36

3

7061 作者的声誉

因为没有人接受答案而且人们(就像我一样)落在这里我会给出我的变化。虽然我不确定这是原来的问题。当导航控制器作为子视图添加到另一个视图时,您必须自己调用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

在nib文件中我有视图,在这个视图下面我有一个标签图像和容器(另一个视图),我把控制器放在里面。这是它的外观。我不得不争抢一些东西,因为这对客户来说很有用。

替代文字

作者: hol 发布者: 04.12.2010 08:53

18

26949 作者的声誉

我终于找到了这个工作的解决方案!

UINavigationControllerDelegate

我认为它的要点是将你的导航控件的委托设置为它所在的viewcontroller,并实现UINavigationControllerDelegate它的两种方法。辉煌!我很兴奋,我终于找到了解决方案!

作者: Chris 发布者: 22.12.2010 10:38

4

2375 作者的声誉

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

其次,您可以使用UITabBarDelegate/ UINavigationBarDelegate来手动转发通知,但我发现要使整个视图调用层次结构正常工作,我所要做的就是手动调用

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

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

..在相应控制器上设置视图控制器之前(仅在分配后)才ONCE。从那时起,它在其子视图控制器上正确调用了这些方法。

我的层次结构是这样的:

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/ UITabBarControllerDelegatemethods 手动调用它们。

旁注:奇怪的是,当它不起作用时,私有方法

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

..你可以从一个工作实现的callstack中看到,通常调用viewWill/Did..方法,但直到我执行上面的操作(即使它被调用)。

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

希望很清楚(ish),乐于回答进一步的问题。

作者: Sam 发布者: 26.07.2011 05:10

-3

108 作者的声誉

您应该只有1个UIViewController随时处于活动状态。您想要操纵的任何子视图应该是 - subVIEWS - 即UIView。

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

  • 应使用单个UIViewController来管理应用程序的“屏幕价值”
  • 使用UINavigationController更改视图

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

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

这是我每次启动应用程序时所做的事情:

  • 从基于窗口的应用程序开始
  • 添加一个UINavigationController作为窗口的rootViewController
  • 添加我想要的第一个UIViewController作为导航控制器的rootViewController

(注意从基于窗口开始只是个人偏好 - 我喜欢自己构建内容,所以我确切地知道它们是如何构建的。它应该可以与基于视图的模板一起工作)

所有事件都正常开火,基本上生活都很好。然后,您可以花费所有时间编写应用程序的重要部分,而不是试图手动破解视图层次结构。

作者: Nigel Flack 发布者: 17.09.2011 11:05

-2

12 作者的声誉

我不确定这是我解决的问题。
在某些情况下,方法不能以正常方式执行,例如“[self methodOne]”。

尝试

- (void)viewWillAppear:(BOOL)animated
{
    [self performSelector:@selector(methodOne) 
           withObject:nil afterDelay:0];
}
作者: Sean 发布者: 16.11.2011 07:35

2

706 作者的声誉

我将此代码用于推送和弹出视图控制器:

推:

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

流行:

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

..它对我来说很好。

作者: Arash Zeinoddini 发布者: 22.06.2012 07:57

1

2185 作者的声誉

我自己就是这个问题,我花了3个小时(其中2个谷歌搜索)来解决它。

结果有帮助的是简单地从设备/模拟器中删除应用程序,清理然后再次运行

希望有所帮助

作者: Finn Gaida 发布者: 21.09.2013 06:18

2

5522 作者的声誉

一个非常常见的错误如下。你有一个视图,UIView* a另一个视图,UIView* b。您将b添加到a作为子视图。如果你试图在b中调用viewWillAppear,它将永远不会被触发,因为它是a的子视图

作者: giuseppe 发布者: 05.12.2013 02:05

3

982 作者的声誉

正确的方法是使用UIViewController包含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];
}
作者: Hari Kunwar 发布者: 28.07.2015 04:47

0

1618 作者的声誉

在我的情况下问题是自定义过渡动画。设置时modalPresentationStyle = .custom viewWillAppear不调用

在自定义过渡动画类中需要调用方法: beginAppearanceTransitionendAppearanceTransition

作者: ober 发布者: 23.10.2018 08:23

1

1791 作者的声誉

对于斯威夫特。首先创建协议以在viewWillAppear中调用您要调用的内容

protocol MyViewWillAppearProtocol{func myViewWillAppear()}

第二,创建类

class ForceUpdateOnViewAppear: NSObject, UINavigationControllerDelegate {
func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool){
    if let updatedCntllr: MyViewWillAppearProtocol = viewController as? MyViewWillAppearProtocol{
        updatedCntllr.myViewWillAppear()
    }
}

}

第三,使ForceUpdateOnViewAppear的实例成为可以访问导航控制器的相应类的成员,并且只要存在导航控制器就存在。它可以是例如导航控制器的根视图控制器或创建或呈现它的类。然后尽早将ForceUpdateOnViewAppear的实例分配给Navigation Controller委托属性。

作者: Vadim Motorine 发布者: 20.12.2018 06:03

0

180 作者的声誉

在我的情况下,这只是ios 12.1模拟器上的一个奇怪的错误。在真实设备上启动后消失。

作者: coldembrace 发布者: 29.01.2019 07:25

0

372 作者的声誉

我创建了一个解决这个问题的类。只需将其设置为导航控制器的委托,并在视图控制器中实现简单的一个或两个方法 - 将在视图即将显示或通过NavigationController显示时调用

这是显示代码的GIST

作者: GregJaskiewicz 发布者: 21.02.2019 10:31

0

463 作者的声誉

ViewWillAppear是UIViewController类的覆盖方法,因此添加一个subView不会调用viewWillAppear,但是当你从viewController呈现,push,pop,show,setFront或popToRootViewController然后viewWillAppear将会调用所呈现的viewController。

作者: Abu Ul Hassan 发布者: 21.02.2019 10:52

0

4000 作者的声誉

谢谢iOS 13。

ViewWillDisappearViewDidDisappearViewWillAppearViewDidAppear不会被调用iOS上13呈现视图控制器,它使用不覆盖整个屏幕一个新的模式呈现上。

积分将归Arek Holko所有。他真的救了我的一天。

在此输入图像描述

作者: BilalReffas 发布者: 14.06.2019 01:54
32x32