ios iPhone viewWillAppear 不触发

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/131062/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 15:17:00  来源:igfitidea点击:

iPhone viewWillAppear not firing

iphoneioscocoa-touch

提问by chzk

I've read numerous posts about people having problems with viewWillAppearwhen you do not create your view hierarchy justright. My problem is I can't figure out what that means.

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

If I create a RootViewControllerand call addSubViewon that controller, I would expect the added view(s) to be wired up for viewWillAppearevents.

如果我创建RootViewController并调用addSubView该控制器,我希望添加的视图为viewWillAppear事件连接起来。

Does anyone have an example of a complex programmatic view hierarchy that successfully receives viewWillAppearevents at every level?

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

Apple's Docs state:

苹果的文档状态:

Warning: If the view belonging to a view controller is added to a view hierarchy directly, the view controller will not receive this message. If you insert or add a view to the view hierarchy, and it has a view controller, you should send the associated view controller this message directly. Failing to send the view controller this message will prevent any associated animation from being displayed.

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

The problem is that they don't describe how to do this. What does "directly" mean? How do you "indirectly" add a view?

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

I am fairly new to Cocoa and iPhone so it would be nice if there were useful examples from Apple besides the basic Hello World crap.

我对 Cocoa 和 iPhone 还是很陌生,所以如果除了基本的 Hello World 废话之外,还有来自 Apple 的有用示例,那就太好了。

回答by mmalc

If you use a navigation controller and set its delegate, then the view{Will,Did}{Appear,Disappear} methods are not invoked.

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

You need to use the navigation controller delegate methods instead:

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

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

回答by lajos

I've run into this same problem. Just send a viewWillAppearmessage to your view controller before you add it as a subview. (There is one BOOL parameter which tells the view controller if it's being animated to appear or not.)

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

[myViewController viewWillAppear:NO];

Look at RootViewController.m in the Metronome example.

查看 Metronome 示例中的 RootViewController.m。

(I actually found Apple's example projects great. There's a LOT more than HelloWorld ;)

(我实际上发现 Apple 的示例项目很棒。不仅仅是 HelloWorld ;)

回答by Chris

I finally found a solution for this THAT WORKS!

我终于找到了一个有效的解决方案!

UINavigationControllerDelegate

UINavigationControllerDelegate

I think the gist of it is to set your nav control's delegate to the viewcontroller it is in, and implement UINavigationControllerDelegateand it's two methods. Brilliant! I'm so excited i finally found a solution!

我认为它的要点是将您的导航控件的委托设置为它所在的视图控制器,并实现UINavigationControllerDelegate它的两种方法。杰出的!我很兴奋,我终于找到了解决方案!

回答by Antoine

I just had the same issue. In my application I have 2 navigation controllers and pushing the same view controller in each of them worked in one case and not in the other. I mean that when pushing the exact same view controller in the first UINavigationController, viewWillAppearwas called but not when pushed in the second navigation controller.

我只是有同样的问题。在我的应用程序中,我有 2 个导航控制器,并且在每个控制器中推送相同的视图控制器在一种情况下工作,而不是在另一种情况下。我的意思是,在第一个中推送完全相同的视图控制器时UINavigationControllerviewWillAppear会调用,但在第二个导航控制器中推送时不会调用。

Then I came across this post UINavigationController should call viewWillAppear/viewWillDisappear methods

然后我遇到了这篇文章UINavigationController 应该调用 viewWillAppear/viewWillDisappear 方法

And realized that my second navigation controller did redefine viewWillAppear. Screening the code showed that I was not calling

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

[super viewWillAppear:animated];

I added it and it worked !

我添加了它并且它起作用了!

The documentation says:

文档说:

If you override this method, you must call super at some point in your implementation.

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

回答by Josh Gagnon

I've been using a navigation controller. When I want to either descend to another level of data or show my custom view I use the following:

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

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

When I do this, I do get the viewWillAppearfunction to fire. I suppose this qualifies as "indirect" because I'm not calling the actual addSubViewmethod myself. I don't know if this is 100% applicable to your application since I can't tell if you're using a navigation controller, but maybe it will provide a clue.

当我这样做时,我确实得到了viewWillAppear触发功能。我想这符合“间接”的要求,因为我addSubView自己没有调用实际的方法。我不知道这是否 100% 适用于您的应用程序,因为我不知道您是否使用导航控制器,但也许它会提供线索。

回答by BilalReffas

Thanks iOS 13.

感谢 iOS 13。

ViewWillDisappear, ViewDidDisappear, ViewWillAppearand ViewDidAppearwon't get called on a presenting view controller on iOS 13 which uses a new modal presentation that doesn't cover the whole screen.

ViewWillDisappear, ViewDidDisappear,ViewWillAppear并且 ViewDidAppear不会在 iOS 13 上的呈现视图控制器上调用,该控制器使用不覆盖整个屏幕的新模式呈现。

Credits are going to Arek Holko. He really saved my day.

学分将归Arek Holko。他真的拯救了我的一天。

enter image description here

在此处输入图片说明

回答by Sam

Firstly, the tab bar should be at the root level, ie, added to the window, as stated in the Apple documentation. This is key for correct behavior.

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

Secondly, you canuse UITabBarDelegate/ UINavigationBarDelegateto forward the notifications on manually, but I found that to get the whole hierarchy of view calls to work correctly, all I had to do was manually call

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

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

and

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

.. just ONCE before setting up the view controllers on the respective controller (right after allocation). From then on, it correctly called these methods on its child view controllers.

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

My hierarchy is like this:

我的层次结构是这样的:

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

Just calling the mentioned methods on the tab/nav controller the first time ensured that ALL the events were forwarded correctly. It stopped me needing to call them manually from the UINavigationBarDelegate/ UITabBarControllerDelegatemethods.

第一次在选项卡/导航控制器上调用上述方法即可确保正确转发所有事件。它使我无需从UINavigationBarDelegate/UITabBarControllerDelegate方法手动调用它们。

Sidenote: Curiously, when it didn't work, the private method

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

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

.. which you can see from the callstack on a working implementation, usually calls the viewWill/Did..methods but didn't until I performed the above (even though it was called).

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

I think it is VERY important that the UITabBarControlleris at window level though and the documents seem to back this up.

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

Hope that was clear(ish), happy to answer further questions.

希望这很清楚(ish),很高兴回答更多问题。

回答by AndrewS

Views are added "directly" by calling [view addSubview:subview]. Views are added "indirectly" by methods such as tab bars or nav bars that swap subviews.

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

Any time you call [view addSubview:subviewController.view], you should then call [subviewController viewWillAppear:NO](or YES as your case may be).

无论[view addSubview:subviewController.view]何时您致电,您都应该致电[subviewController viewWillAppear:NO](或根据您的情况选择是)。

I had this problem when I implemented my own custom root-view management system for a subscreen in a game. Manually adding the call to viewWillAppear cured my problem.

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

回答by hol

As no answer is accepted and people (like I did) land here I give my variation. Though I am not sure that was the original problem. When the navigation controller is added as a subview to a another view you must call the viewWillAppear/Dissappear etc. methods yourself like this:

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

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

    [subNavCntlr viewWillAppear:animated];
}

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

    [subNavCntlr viewWillDisappear:animated];
}

Just to make the example complete. This code appears in my ViewController where I created and added the the navigation controller into a view that I placed on the view.

只是为了使示例完整。这段代码出现在我创建的 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];
}

the .h looks like this

.h 看起来像这样

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

@end

In the nib file I have the view and below this view I have a label a image and the container (another view) where i put the controller in. Here is how it looks. I had to scramble some things as this was work for a client.

在 nib 文件中,我有视图,在此视图下方有一个标签,一个图像和一个容器(另一个视图),我将控制器放入其中。这是它的外观。我不得不争先恐后地处理一些事情,因为这是为客户工作的。

alt text

替代文字

回答by Hari Kunwar

Correct way to do this is using UIViewController containment api.

正确的方法是使用 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];
}