【问题标题】:Avoid creation of multiple ViewController instances, iOS Swift避免创建多个 ViewController 实例,iOS Swift
【发布时间】:2018-03-10 01:12:54
【问题描述】:

在 AppDelegate 中,每当收到 VoIP 呼叫(推送通知)时,都会调用以下函数,从而创建多个“VideoCallViewController”实例

如下所示,我使用 deinit(在 VideoCallViewController 中)来检查是否在创建新的“VideoCallViewController”实例之前取消了先前的“VideoCallViewController”实例,令我惊讶的是print("Deinitializing VC) 不是t 调用,将实例留在内存中。

如果 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()

}

【问题讨论】:

  • 如果你想确保只创建一个实例,为什么不创建一个单例?
  • 单例视图控制器不是一个好主意;首先,很难从情节提要中初始化一个。您应该能够让您当前的视图控制器在您的应用程序委托上存储对自身的引用。然后,您可以轻松地调用当前视图控制器上的函数来处理调用。
  • @Paulw11,您能否详细说明您的建议?

标签: ios swift swift3 uiviewcontroller uinavigationcontroller


【解决方案1】:

您可以在 AppDelegate 中创建一个惰性 var

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

}

【讨论】:

    【解决方案2】:

    可能的解决方案:创建单例持有对可空窗口的引用,负责视频通话流程。在通知更改可见窗口。通话结束 - 返回应用程序主窗口。

    例如:

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

    【讨论】:

    • 感谢您的建议,当用户结束通话时,我不想关闭窗口,而只是关闭相关视图并让用户从他登陆的位置浏览应用程序,类似于 WhatsApp .
    • 谢谢,您的回答说明了解决问题的方法。
    猜你喜欢
    • 2014-08-17
    • 1970-01-01
    • 2015-11-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-04
    • 2021-09-04
    • 2014-08-11
    • 1970-01-01
    相关资源
    最近更新 更多