简体   繁体   English

为什么执行 segue 后我的 properties 和 outlets 变为 nil?

[英]Why do my properties and outlets become nil after performing a segue?

I am learning Swift and currently using two ViewControllers in a project.我正在学习 Swift,目前在一个项目中使用两个 ViewController。 The first controller initializes data and performs a segue to the second.第一个 controller 初始化数据并对第二个执行 segue。 The second ViewController adds a new value to a variable passed in from the first ViewController.第二个 ViewController 将一个新值添加到从第一个 ViewController 传入的变量中。 However, when I dismiss the segue and try to update the first one, all IBOutlet properties and variables suddenly become nil.但是,当我关闭 segue 并尝试更新第一个时,所有 IBOutlet 属性和变量突然变为 nil。 This was derived by logging properties in the updateViewController() method of the firstViewController.这是通过在 firstViewController 的 updateViewController() 方法中记录属性得出的。 Thank you in advance.先感谢您。

First ViewController第一个视图控制器

class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {


    // Date Label
    @IBOutlet weak var dateLabel: UILabel!

    // Progress Bar
    @IBOutlet weak var progressBar: UIProgressView?

    // Progress Label
    @IBOutlet weak var progressLabel: UILabel!

    // Button Collection View
    @IBOutlet weak var collectionView: UICollectionView!

    // Current goal button
    @IBOutlet weak var currentGoal: UIButton!

    // Goal label
    @IBOutlet weak var goalLabel: UILabel!

    // Variable Initialization

    // Initialize daily water goal
    var dailyGoal = Float(20)

    // Initialize current progress
    var currentProgress = Float()

    // Water counter variable
    var waterDrank = Float(0)

    var percentageProgress = Float(0.0)

    override func viewDidLoad() {
        super.viewDidLoad()

    progressBar?.setProgress(0.0, animated: false)
        progressBar!.transform = progressBar!.transform.scaledBy(x: 1, y: 3)

    }

    // MARK: - Button & Progress View Logic

    func addProgress(amount: Float) {

        // Add amount to the total amount drank
        waterDrank += amount
        print(waterDrank)

        // Get the current progress in relation to the daily goal
        let currentProgress = waterDrank / dailyGoal
        // Set the new progress to the progressBar
        progressBar?.setProgress(currentProgress, animated: true)

        // Check if progress is below 0

        if (dailyGoal - waterDrank) <= 0.0 {
        // done
        }

        // Check if the daily goal has already been achieved
        if waterDrank >= Float(dailyGoal) {

            // Daily goal has been achieved - show message & abort code
            showAlert(title: "done", message: "!!")

            return

        }

    }

        // MARK: - Segue Action

    // Segue button to second view controller
    @IBAction func changeGoal(_ sender: Any) {

        performSegue(withIdentifier: "currentGoal", sender: self)

    }

    // Save variables
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

        let secondViewController = segue.destination as! SecondViewController
        secondViewController.dailyGoal = self.dailyGoal

    }

    func updateViewController() {

        // Log new daily goal
        print(dailyGoal)

        // Print progressBar object
        print(waterDrank) // is 0, despite waterDrank having been increased in value before performing segue

        print(progressBar?.progress) // is nil, despite having not been nil before performing segue

    }



}

Second ViewController第二个视图控制器

    // Current goal label
    @IBOutlet weak var currentGoal: UILabel!

    // Goal picker
    @IBOutlet weak var goalPicker: UIPickerView!


    var dailyGoal = Float()

    let newDailyGoal = [Int()]

    // Initialize current progress
    var currentProgress = Float()

    // Water counter variable
    var waterDrank = Float(0)

    var percentageProgress = Float(0.0)

    override func viewDidLoad() {
        super.viewDidLoad()

    // setting secondViewController as delegate & data source for the UIPicker
    }

    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {

        let vc = ViewController()
        let newDailyGoal = [1500, 1750, 2000, 2250, 2500]
        // Consider row

            switch row {

            case 0:
                self.dailyGoal = Float(newDailyGoal[0])
                vc.dailyGoal = self.dailyGoal

            case 1:
                self.dailyGoal = Float(newDailyGoal[1])
                vc.dailyGoal = self.dailyGoal

            case 2:
                self.dailyGoal = Float(newDailyGoal[2])
                vc.dailyGoal = self.dailyGoal

            case 3:
                self.dailyGoal = Float(newDailyGoal[3])
                vc.dailyGoal = self.dailyGoal

            case 4:
                self.dailyGoal = Float(newDailyGoal[4])
                vc.dailyGoal = self.dailyGoal

            default:

                print("daily goal is default: \(dailyGoal)")

            }


        // Export to ViewController.swift
        return "\(Int(dailyGoal)) ml"

    }

    // MARK: - Save button segue logic

    @IBAction func doneButton(_ sender: Any) {

        dismiss(animated: true, completion: nil)
        let firstViewController = ViewController()
        firstViewController.updateViewController()

    }

}

Your scenario requires you to pass the ViewController instance to the SecondViewController instead of creating a new one as you've done here.您的场景要求您将ViewController实例传递给SecondViewController而不是像您在此处所做的那样创建一个新实例。 And then make a call for the function updateViewController in your done button action.然后在完成按钮操作中调用 function updateViewController So here's what you need to update.因此,这是您需要更新的内容。

In ViewController:在视图控制器中:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    let secondViewController = segue.destination as! SecondViewController
    secondViewController.dailyGoal      = dailyGoal
    secondViewController.viewController = self
}

And in SecondViewController:在 SecondViewController 中:

class SecondViewController: UIViewController {
    weak var viewController: ViewController?
...

    @IBAction func doneButton(_ sender: Any) {
        dismiss(animated: true)
        viewController?.updateViewController()
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM