为什么让viewController解雇自己是不好的做法?

时间:2015-07-03 10:50:09

标签: ios swift uiviewcontroller

我有两个视图控制器,(cond ((and (list? tree) (null? (cadr tree)) ; the second element is '() (null? (caddr tree))) ; the third element is '() (list x)) ... ...) MainVC

当用户点击ModalVC上的按钮时,会出现模态视图控制器。

然后,用户可以点击另一个按钮将其关闭并返回主按钮。

我尝试过这两种方法并且它们都完成了同样的事情:它们解雇了模态视图控制器:

MainVC

正如我所说的那样正常,但考虑另一种方法:使用委托让主控制器解雇:

//method 1:
//  File: ModalVC.swift
//
@IBAction func dismissTapped() {
     self.dismissViewControllerAnimated(false, completion: nil);
}

并在主视图控制器上自定义类文件:

// method 2: part A 
// File: ModalVC.swift
// 
protocol ModalVCDelegate {
    func modalVCDismissTapped();
}
...
...
...
var delegat:ModalVCDelegate? = nil;
...
...
@IBAction func dismissTapped() {
    delegate.modalVCDismissTapped();
}

由于这两种方法是必要的,我应该担心任何可能的内存泄漏吗?

任何解释都会有所帮助

3 个答案:

答案 0 :(得分:15)

使用委托是解除视图控制器的最佳和更灵活的方法 它的目的是在你的代码中的某些未来或其他地方你可以重用这个VC,但由于某些原因你可能不会将它呈现为模态,而是推入导航堆栈。所以你的ModalVC不知道它是如何呈现的,但代表确实如此 在这种情况下,您的代码中可以有2个位置

  1. 您呈现模态和委托调用

    [self dismiss...]
    
  2. 您将其推入导航堆栈并委派调用

    [self.navigationController popView...]
    
  3. 您将其添加为子VC并委派调用

    [someParentVC removeChild..] 
    

    或任何其他适当的工作流程以将其删除。

答案 1 :(得分:0)

Modo Ltunzher的答案很好。 我个人更喜欢将闭包传递给“孩子”,孩子完成后会回呼“父亲”并获得奖金,我也可以传递值/结果。

一个例子:我展示了一个QRCode,它将在识别到qrcode时关闭并回调:

extension UIViewController {


    func presentQRCode( pushed: Bool, callback: @escaping QRCodeCallBack){

        let qrVC = ScanQRCodeController(nibName: "ScanQRCodeController", bundle: nil)
        qrVC.callback = callback

        if pushed{
            let nc = self.navigationController!
            nc.pushViewController(qrVC, animated: true)

        }else{
            self.present(qrVC, animated: true, completion: nil)
        }

    }


    func dismissQRCode(pushed: Bool){

        if pushed{
            let nc = self.navigationController!
            nc.popViewController(animated: true)
        }else{
            self.dismiss(animated: true, completion: nil)
        }
    }
}

在“父亲”中

   @IBAction func doScanCodeAction(_ sender: UIBarButtonItem) {
        let pushed = true
        self.presentQRCode(pushed: pushed, callback: { (string: String?) in

            if let qrCode = string{
                self.fillFieldsWith(qrCode: qrCode)
            }else{
                #if DEBUG
                print("QR code error")
                #endif
            }

            self.dismissQRCode(pushed: pushed)
        }
        )
    }

答案 2 :(得分:0)

呈现的视图控制器目前不知道它正在呈现,因此它不应该知道自己关闭。

Apple 建议从呈现视图控制器 https://developer.apple.com/documentation/uikit/uiviewcontroller/1621505-dismiss

中解除呈现的视图控制器

为避免在您的情况下发生泄漏,请始终将您的委托变量声明为 weak。 为此,您的协议应从 AnyObject 继承。

protocol ModalVCDelegate: AnyObject {
   func modalVCDismissTapped()
}

weak var delegate: ModalVCDelegate?

另一种方法是在呈现的 VC 上创建一个闭包变量,并在呈现的 VC 上初始化它后传递 dismiss 操作,然后在对上的操作调用闭包提交的 VC。

演示 VC 设置

class PresentingViewController: UIViewController {
  @IBAction func buttonTapped(_ sender: Any) {
     let presentedVC = PresentedViewController()
     presentedVC.modalPresentationStyle = .fullScreen
     presentedVC.onDismissAction = { [weak self] in
       self?.dismiss(animated: true)
     }
     self.present(presentedVC, animated: true, completion: nil)
  }
}

提供用于关闭的 VC 设置

class PresentedViewController: UIViewController {
  var onDismissAction: (() -> Void)?

  @IBAction func exitButtonTapped(_ sender: Any) {
    onDismissAction?()
  }
}
相关问题