避免创建多个ViewController实例,iOS Swift

时间:2017-09-28 10:18:15

标签: ios swift swift3 uiviewcontroller uinavigationcontroller

在AppDelegate中,只要收到VoIP呼叫(推送通知),就会调用以下函数,从而创建" VideoCallViewController"

的多个实例

我已经使用了deinit(在VideoCallViewController中),如下所示,检查以前的" VideoCallViewController"在一个新的" VideoCallViewController"的实例之前被去初始化了。创建后,令我惊讶的是print("Deinitializing VC)没有被调用,将实例留在内存中。

如果AppDelegate中已存在VideoCallViewController实例,如何向其中显示VideoCallViewController及其导航控制器。

在VideoCallViewController中

deinit {
  print("Deinitializing VC)
}

在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()

}

2 个答案:

答案 0 :(得分:2)

您可以在AppDelegate中创建一个懒惰的变种

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

然后在你的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()

}

答案 1 :(得分:1)

可能的解决方案:创建包含可空窗口的单例控件,负责视频调用流程。在通知上更改可见窗口。在通话结束时 - 返回应用程序主窗口。

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

你的方法看起来像:

func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, forType type: PKPushType) {
    VideoCallManager.sharedInstance.navigateToVideoCallViewController()
}