iPhone viewWillAppear没有开火

问题描述 投票:114回答:25

当你没有正确地创建你的视图层次时,我已经阅读了很多关于viewWillAppear遇到问题的人的帖子。我的问题是我无法弄清楚这意味着什么。

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

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

Apple的Docs声明:

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

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

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

iphone ios cocoa-touch
25个回答
2
投票

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

推:

- (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];
}

流行:

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

..它对我来说很好。


2
投票

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


2
投票

谢谢iOS 13。

UIView* bViewWillDisappearViewDidDisappearViewWillAppear将不会在iOS 13上的呈现视图控制器上调用,该控制器使用不覆盖整个屏幕的新模式演示。

积分将去ViewDidAppear。他真的救了我的一天。

Arek Holko


1
投票

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


1
投票

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


1
投票

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

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

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

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


1
投票

如果这有助于任何人。我有一个类似的问题,我的[viewController.view addSubview:anotherViewController.view]没有射击ViewWillAppear。经过大量的游戏,我意识到问题是控制我的UITableViewControllerUINavigationController不在根视图上。一旦我解决了这个问题,它现在就像一个冠军。


1
投票

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

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

希望有所帮助


1
投票
UITableView

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


1
投票

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

[self.navigationController setDelegate:self];

第二,创建类

protocol MyViewWillAppearProtocol{func myViewWillAppear()}

}

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


0
投票

在我的情况下问题是自定义过渡动画。当设置class ForceUpdateOnViewAppear: NSObject, UINavigationControllerDelegate { func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool){ if let updatedCntllr: MyViewWillAppearProtocol = viewController as? MyViewWillAppearProtocol{ updatedCntllr.myViewWillAppear() } } modalPresentationStyle = .custom没有调用

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


0
投票

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


0
投票

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

endAppearanceTransition


0
投票

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


-2
投票

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

尝试

Here's the GIST showing the code

-3
投票

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

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

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

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

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

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

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

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

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

© www.soinside.com 2019 - 2024. All rights reserved.