5

In AppDelegate, the below function gets called whenever VoIP call (push notification) is received thereby creating multiple instances of "VideoCallViewController"

I've used deinit (in VideoCallViewController) as shown below, to check if the previous instance of "VideoCallViewController" was being de-initialised before a new instance of "VideoCallViewController" is created, to my surprise print("Deinitializing VC) wasn't called, leaving the instance in memory.

How can I show VideoCallViewController with its Navigation Controller if an instance of VideoCallViewController already exists from AppDelegate.

In VideoCallViewController

deinit {
  print("Deinitializing VC)
}

In AppDelegate

func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, forType type: PKPushType) {

    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    videoVC = storyboard.instantiateViewController(withIdentifier: "VideoCallViewController") as! VideoCallViewController

    self.window = UIWindow(frame: UIScreen.main.bounds)
    self.window?.rootViewController = videoVC
    self.window?.makeKeyAndVisible()

}
SpaceX
  • 2,814
  • 2
  • 42
  • 68
  • 3
    Why don't you create a singleton if you want to make sure that only one instance will be created? – Tamás Sengel Sep 28 '17 at 10:18
  • A singleton viewcontroller isn’t a great idea; for a start, it would be hard to initialise one from a storyboard. You should be able to have your current view controller store a reference to itself on your app delegate. Then, you can easily call a function on the current view controller to handle the call. – Paulw11 Sep 28 '17 at 10:25
  • try it :- https://stackoverflow.com/questions/45582523/how-to-push-user-to-viewcontroller-from-non-uiview-class/45583476#45583476 – Salman Ghumsani Sep 28 '17 at 10:41
  • @Paulw11, could you please shed more light on your advice ? – SpaceX Sep 28 '17 at 10:46

2 Answers2

2

You can create a lazy var in your AppDelegate

lazy var videoVC: UIViewController = {
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    return storyboard.instantiateViewController(withIdentifier: "VideoCallViewController")
}()

Then in your pushRegistry:

func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, forType type: PKPushType) {

    self.window = UIWindow(frame: UIScreen.main.bounds)
    self.window?.rootViewController = self.videoVC
    self.window?.makeKeyAndVisible()

}
Y.Bonafons
  • 2,329
  • 13
  • 20
1

Possible solution: Create singleton holding reference to nullable window, responsible for video calls flow. On notification change visible windows. On call end - return to the application main window.

E.G. :

class VideoCallManager {
    //MARK: - Singleton
    static let sharedInstance = VideoCallManager()
    private init() {}

    private var videoCallWindow: UIWindow?

    func navigateToVideoCallViewController() {
        if let window = self.videoCallWindow, window.keyWindow {
             //VideoCallViewController is displayed at the moment.
             return
        }

        videoCallWindow = UIWindow.init(frame: UIScreen.mainScreen().bounds)
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        videoVC = storyboard.instantiateViewController(withIdentifier: "VideoCallViewController") as! VideoCallViewController

        self.videoCallWindow?.rootViewController = videoVC
        self.videoCallWindow?.makeKeyAndVisible()
    }

    func returnToWindowOfAppDelegate() {
        if let window = self.videoCallWindow, window.keyWindow {
            (UIApplication.sharedApplication().delegate as? AppDelegate)?.window?.makeKeyAndVisible()

            self.videoCallWindow = nil
        }
    }
}

And your method would look like:

func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, forType type: PKPushType) {
    VideoCallManager.sharedInstance.navigateToVideoCallViewController()
}
dvp.petrov
  • 1,110
  • 13
  • 20
  • thanks for the advice, when the user ends the call I do not want to close the window but instead just close the related views and let the user navigate through the app from where he landed, similar to WhatsApp. – SpaceX Sep 29 '17 at 00:37
  • Thanks, your answer showed the way to resolve the issue. – SpaceX Oct 05 '17 at 06:05