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

How to determine whether current view controller is active, and execute code if active

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

同时,我对通知和观察者了解不多(如果确实需要的话),因此,您能否在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
        }
    }

正如我在评论中提到的,我不使用故事板。可能有一种方法可以创建 unwind segue - 也可能不会 - 但 [这里有一个 link][1] 可以帮助您使用仅故事板的方式来解决您的问题。快速搜索“模态”找到 9 个匹配项,第二个开始详细介绍。

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

您可能想稍微改变一下您的概念 - 一个应用程序 window(想想 AppDelegate and/or SceneDelegate 变成 active,其中 UIViewController 有一个 initializeddeinitialized,还有一个根 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)
}

这不会发送任何数据,只会发送模态框消失的事实。如果你想发送数据——比如说,一个字符串或一个 table 单元格值,将 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() 的任何引用。尝试将视图(和视图控制器)视为 appearing/disappearing,而不是 background/foreground。
  • 虽然第一个视图在背景中可见,但它仍然可见。所以诀窍是针对模态视图的消失进行编码。