【问题标题】:De-initialzing a ViewController after dismissal?解雇后取消初始化 ViewController?
【发布时间】:2020-07-06 11:31:43
【问题描述】:

我的App中有两个viewController,第一个viewController的代码如下图:

           import UIKit

            class firstViewController: UIViewController {

              // The below two variables will be passed from the firstViewController to the secondViewController then back again from the secondViewController to the firstViewController:

              var selectedRowValue: Int = 0

              var selectedSectionValue: Int = 0

              let main = UIStoryboard(name: "Main", bundle: nil)

               lazy var secondViewController = main.instantiateViewController(withIdentifier: "secondViewController")

             override func viewDidLoad() {

             super.viewDidLoad()

              }

    // The below function will be triggered when the user tap on a specific tableView cell detailClosure icon. This is when the needed data get sent from this viewController to the secondViewController:

            func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) {

             let secondViewControllerProperties = secondViewController as! secondViewController

              secondViewControllerProperties.receivedSelectedSectionValueFromFirstVc = indexPath.section

              secondViewControllerProperties.receivedSelectedRowValueFromFirstVc = indexPath.row

    // The below is the relevant content of a UILabel inside the tapped tableView cell by the user that get send to the secondViewController for it to be displayed as its NavigationBar title:

             secondViewControllerProperties.selectedUniversalBeamSectionDesignation = arrayWithAllDataRelatedToUbsSections.filter({ $0.sectionSerialNumber == "\(arrayWithAllSectionsSerialNumbers[indexPath.section])" }).map({ $0.fullSectionDesignation })[indexPath.row]

self.present(secondViewControllerProperties, animated: true, completion: nil)

             }

            }

    // The below extension inside the firstViewController is used to pass data back from the secondViewController to the firstViewController:

        extension firstViewController: ProtocolToPassDataBackwardsFromSecondVcToFirstVc {

            func dataToBePassedUsingProtocol(passedSelectedTableSectionNumberFromPreviousVc: Int, passedSelectedTableRowNumberFromPreviousVc: Int) {

                self.selectedRowValue = passedSelectedTableRowNumberFromPreviousVc

                self. selectedSectionValue = passedSelectedTableSectionNumberFromPreviousVc

        }

        }

下面是第二个视图控制器的代码:

import UIKit

class secondViewController: UIViewController {

    weak var delegate: ProtocolToPassDataBackwardsFromSecondVcToFirstVc?

// The below variables get their values when the data get passed from the firstViewController to the secondViewController:

    var receivedSelectedRowValueFromFirstVc: Int = 0

    var receivedSelectedSectionValueFromFirstVc: Int = 0

   var selectedUniversalBeamSectionDesignation: String = ""

// Inside the below navigationBar declaration, its labelTitleText will depend on the tapped tableViewCell by the user inside the firstViewController:

lazy var navigationBar = CustomUINavigationBar(navBarLeftButtonTarget: self, navBarLeftButtonSelector: #selector(navigationBarLeftButtonPressed(sender:)), labelTitleText: "UB \(selectedUniversalBeamSectionDesignation)", navBarDelegate: self)

    override func viewDidLoad() {

        super.viewDidLoad()

        view.addSubview(navigationBar)

}

// The below gets triggered when the user hit the back button inside the navigationBar of the secondViewController. This is where using the Protocol data get passed back to the firstViewController: 

extension secondViewController: UINavigationBarDelegate {

    @objc func navigationBarLeftButtonPressed(sender : UIButton) {

        if delegate != nil {

            delegate?.dataToBePassedUsingProtocol(passedSelectedTableSectionNumberFromPreviousVc: self.selectedTableSectionNumberFromPreviousViewController, passedSelectedTableRowNumberFromPreviousVc: self.selectedTableRowNumberFromPreviousViewController)

        }

        dismiss(animated: true) {}

    }

}

但是,我注意到的是,当用户点击 secondViewController 的导航栏中的后退按钮时,每当 secondViewController 被关闭时。 secondViewController 没有被取消初始化,因此,每当我在 firstViewController 内的 tableView 内按下不同的单元格时,在 secondViewController 内显示的导航栏标题仍然与我第一次按下时显示的标题相同。由于 secondViewController 没有取消初始化,因此我看到的值与第一次初始化时相同。

我的问题是如何在 secondViewController 被解除时取消初始化它,以便每次我点击 firstViewController 内的 tableView 内的不同单元格时,都会初始化一个新的 secondViewController?

【问题讨论】:

  • 正如 Moshe 所说,问题在于您的第一个视图控制器对第二个视图控制器保持强引用。这是没有必要的。只需将第二个视图控制器的引用作为accessoryButtonTappedForRowWith 方法中的局部变量即可。此外,您还没有共享 CustomUINavigationBar,但请确保它对其委托保持弱引用。
  • 一旦你的直接问题抛诸脑后,你可能想重新审视你的班级名称。按照惯例,类名总是以大写字母开头。对于变量、属性等,我们以小写字母开头,但类型总是以大写字母开头。而且,如果您想简化重命名过程(同时在各处更改它们,包括情节提要),您可以右键单击类名并选择“重构”»“重命名...”。
  • 谢谢 Rob,我会在考虑您非常感谢的建议后重构我的代码 :)

标签: swift uiviewcontroller protocols deinit


【解决方案1】:

您的代码生成一次secondViewController 并重复使用它(它是一个属性)。

               lazy var secondViewController = main.instantiateViewController(withIdentifier: "secondViewController")

这意味着它将一直存在,直到第一个视图控制器被销毁,当然 - 将被重用。
相反,您应该根据需要创建它。

func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) {
             // Create the second view controller
             let secondViewController = main.instantiateViewController(withIdentifier: "secondViewController")

             let secondViewControllerProperties = secondViewController as! secondViewController

              secondViewControllerProperties.receivedSelectedSectionValueFromFirstVc = indexPath.section

              secondViewControllerProperties.receivedSelectedRowValueFromFirstVc = indexPath.row

    // The below is the relevant content of a UILabel inside the tapped tableView cell by the user that get send to the secondViewController for it to be displayed as its NavigationBar title:

             secondViewControllerProperties.selectedUniversalBeamSectionDesignation = arrayWithAllDataRelatedToUbsSections.filter({ $0.sectionSerialNumber == "\(arrayWithAllSectionsSerialNumbers[indexPath.section])" }).map({ $0.fullSectionDesignation })[indexPath.row]

self.present(secondViewControllerProperties, animated: true, completion: nil)

             }

            }

删除lazy var当然不再需要了。
另外,您可以这样做:
let secondViewController = main.instantiateViewController(withIdentifier: "secondViewController") as! SecondViewController 而不是稍后再投射,这样会更干净一些。

【讨论】:

  • 非常感谢 Moshe,您的回复解决了我的问题。再次非常感谢,我完全同意铸造点。
猜你喜欢
  • 2019-12-31
  • 2021-03-16
  • 1970-01-01
  • 2020-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-16
相关资源
最近更新 更多