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

邮差的信 提交于 2021-01-07 02:55:45

问题


In my app, there is a ViewController.swift file and a popupViewController.swift file. Inside the app, when I open the popupViewController with storyboard segue as presentModally and then come back from popupViewController to ViewController with the code dismiss(), the methods viewDidLoad, viewWillAppear, viewDidAppear, ViewWillLayoutSubviews etc. nothing works, they execute just once and don't repeat when I go and return back. So, I want to execute the code every time when viewController.swift is active. I couldn't find a useful info in stackoverflow about this.

Meanwhile, I don't know much about notification and observers(if certainly needed), therefore, can you tell step by step in detail how to do that in Swift (not objective-c)? I mean how to determine if current view controller is active.

Edit: I am navigating from StoryBoard segue, presentModally. There is no Navigation Controller in storyboard.

I tried some codes but nothing happens. The point I came so far is:

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
        }
    }

回答1:


As mention in my comments, I don't use storyboards. There may be a way to create an unwind segue - or maybe not - but [here's a link][1] that may help you with a storyboard-only way of fixing your issue. A quick search on "modal" turned up 9 hits, and the second one starts going into details.

I'm thinking the issue is with what modality is. Basically, your first view controller, which properly executed viewDidAppear, is still visible. So it's effectively not executing viewDidDisappear when your second VC is presented.

You might want to change your concept a bit - an application window (think AppDelegate and/or SceneDelegate become active, where a UIViewController has a is initialized and deinitialized, along with a root UIView that is loaded, appears* and disappears*. This is important, because what you want to do is send your notification from the modal VC's viewDidDisappear override.

First, I find it easiest to put all your notication definitions in an extension:

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

This helps not only reduce string typos but also is allows Xcode's code completion to kick in.

Next, in your first view controller, ad an observer to this notification:

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")
}

I've added both forms of init for clarity. Since you are using a storyboard, I'd expect that init(coder:) is the one you need.

Finally, just send the notification when the modal has disappeared:

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

This sends no data, just the fact that the modal has disappeared. If you want to send data - say, a string or a table cell value, change the object parameter to it:

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

And make the following changes in your first 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)
}

Last notes:

  • To repeat, note that by declaring an extension to Notification.Name, I've only have one place where I'm declaring a string.
  • There is no code in AppDelegate or SceneDelegate, nor any references to `UIApplication(). Try to think of the view (and view controller) as appearing/disappearing, not background/foreground.
  • While the first view is visually in the background, it's still visible. So the trick is to code against the modal view disappearing instead.


来源:https://stackoverflow.com/questions/65268350/how-to-determine-whether-current-view-controller-is-active-and-execute-code-if

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!