如何确定当前视图控制器是不是处于活动状态,如果处于活动状态则执行代码

Posted

技术标签:

【中文标题】如何确定当前视图控制器是不是处于活动状态,如果处于活动状态则执行代码【英文标题】:How to determine whether current view controller is active, and execute code if active如何确定当前视图控制器是否处于活动状态,如果处于活动状态则执行代码 【发布时间】:2020-12-12 18:24:23 【问题描述】:

在我的应用程序中,有一个 ViewController.swift 文件和一个 popupViewController.swift 文件。在应用程序内部,当我打开带有故事板 segue 为 presentModally 的 popupViewController,然后使用代码 dismiss() 从 popupViewController 返回到 ViewController 时,方法 viewDidLoad, viewWillAppear, viewDidAppear, ViewWillLayoutSubviews 等没有任何作用,它们只执行一次,当我执行时不要重复回去。所以,我想在每次 viewController.swift 处于活动状态时执行代码。我在 *** 中找不到关于此的有用信息。

同时,我对通知和观察者不太了解(如果确实需要的话),因此,您能否逐步详细说明如何在 Swift 中做到这一点(不是objective-c) ?我的意思是如何确定当前视图控制器是否处于活动状态。

编辑:我正在从 StoryBoard segue 导航,presentModally。故事板中没有导航控制器。

我尝试了一些代码,但没有任何反应。我到目前为止的重点是:

override func viewDidLoad() 
        super.viewDidLoad()
    NotificationCenter.default.addObserver(self, selector:#selector(appWillEnterForeground), name:UIApplication.willEnterForegroundNotification, object: nil) 


@objc func appWillEnterForeground() 
        print("asdad") //nothing happens
        if self.viewIfLoaded?.window != nil 
            // viewController is visible
            print("CURRENT VİEW CONTROLLER") //nothing happens
        
    

【问题讨论】:

通过UINavigationController 在视图控制器之间来回导航时会调用所有这四个。你是如何向前和向后导航的?你能提供一些代码吗? @gmdev 我正在从 StoryBoard segue 导航,presentModally。现在更新了添加这一行的帖子 我不使用故事板,但这听起来相当于一个 VC 做另一个的 present。如果是这样,也许你可以让第一个 VC 成为模态的代表,告诉它它正在被解雇。 我刚刚评论了你的另一个问题。这两个有关系吗? (似乎是。)我并不是要批评。相反,我还有一个问题 - 与我对您的其他问题的问题有些相关。 :-) 如果您只想 (a) 展示一个 VC,然后 (b) 以模态方式展示第二个 VC,为什么 用代码而不是故事板来做呢?你对事物有更多的控制权。 @AnthonSanthez 当您以模态方式呈现视图控制器时,您设置的.modalPresentationStyle 是什么? 【参考方案1】:

正如我在 cmets 中提到的,我不使用故事板。可能有一种方法可以创建一个放松的转场 - 或者可能没有 - 但 [这里有一个链接][1] 可以帮助您使用仅故事板的方式来解决您的问题。快速搜索“modal”找到了 9 个点击,第二个开始详细介绍。

我认为问题在于模态是什么。基本上,正确执行viewDidAppear 的第一个视图控制器仍然可见。因此,当您的第二个 VC 出现时,它实际上并没有执行 viewDidDisappear

您可能想稍微改变一下您的概念 - 应用程序窗口(想想 AppDelegate 和/或 SceneDelegate 变为活动,其中 UIViewController 有一个 已初始化 和 deinitialized,以及一个 已加载 的根 UIView,出现*和消失*。这很重要,因为您要做的是发送您的来自模态 VC 的 viewDidDisappear 覆盖的通知。

首先,我发现将所有通知定义放在扩展中是最容易的:

extension Notification.Name 
    static let modalHasDisappeared = Notification.Name("ModalHasDisappeared")

这不仅有助于减少字符串拼写错误,还可以让 Xcode 的代码完成功能发挥作用。

接下来,在您的第一个视图控制器中,为该通知添加一个观察者:

init() 
    super.init(nibName: nil, bundle: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(modalHasDisappeared), name: .modalHasDisappeared, object: nil)

required init?(coder: NSCoder) 
    super.init(coder: coder)
    NotificationCenter.default.addObserver(self, selector: #selector(modalHasDisappeared), name: .modalHasDisappeared, object: nil)

@objc func modalHasDisappeared() 
    print("modal has disappeared")

为了清楚起见,我添加了init两种 形式。由于您使用的是故事板,我希望 init(coder:) 是您需要的。

最后,当模态消失时发送通知:

override func viewDidDisappear(_ animated: Bool) 
    super.viewDidDisappear(animated)
    NotificationCenter.default.post(name: .modalHasDisappeared, object: nil, userInfo: nil)

这不会发送任何数据,只是模式已消失的事实。如果你想发送数据——比如说,一个字符串或者一个表格单元格的值,把object参数改成它:

NotificationCenter.default.post(name: .modalHasDisappeared, object: myLabel, userInfo: nil)

并在您的第一个 VC 中进行以下更改:

NotificationCenter.default.addObserver(self, selector: #selector(modalHasDisappeared(_:)), name: .modalHasDisappeared, object: nil)

@objc func modalHasDisappeared(_ notification:Notification) 
    let label = notification.object as! UILabel!
    print(label.text)

最后的笔记:

重复一遍,请注意,通过声明Notification.Name 的扩展名,我只有一个地方声明了一个字符串。 AppDelegateSceneDelegate 中没有代码,也没有任何对 `UIApplication() 的引用。尝试将视图(和视图控制器)视为出现/消失,而不是背景/前景。 虽然第一个视图在背景中可视,但它仍然可见。所以诀窍是针对模态视图进行编码而不是消失。

【讨论】:

非常感谢您的详细解释,这是对正在发生的事情的一个很好的总结。我使用不同的转义方法处理了这个问题,所以当我摆脱转义替代方案时,我会尝试你的答案:) 不过,我接受你的回答,因为我感谢你的努力和逐步理解的教学风格。这些信息将帮助其他人像我一样理解底层逻辑,谢谢..

以上是关于如何确定当前视图控制器是不是处于活动状态,如果处于活动状态则执行代码的主要内容,如果未能解决你的问题,请参考以下文章

如何确定 Skype 通话当前是不是在 Android 上处于活动状态

iOS 如何知道哪个视图控制器应该处于活动状态?

如何确定夏令时是不是在 C 中处于活动状态?

确定夏令时 (DST) 在 Java 中是不是在指定日期处于活动状态

C Windows API 确定用户是不是处于非活动状态,包括播放媒体

Laravel 5.4 检查用户是不是处于活动状态,如果没有则回复消息