为什么执行 segue 后我的属性和网点变为零?
Why do my properties and outlets become nil after performing a segue?
我正在学习 Swift,目前在一个项目中使用两个 ViewController。第一个控制器初始化数据并执行到第二个的 segue。第二个 ViewController 将一个新值添加到从第一个 ViewController 传入的变量中。但是,当我关闭 segue 并尝试更新第一个时,所有 IBOutlet 属性和变量突然变为 nil。这是通过在 firstViewController 的 updateViewController() 方法中记录属性得出的。提前谢谢你。
第一个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
}
}
第二个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()
}
}
您的方案要求您将 ViewController
实例传递给 SecondViewController
,而不是像您在此处所做的那样创建一个新实例。然后在完成按钮操作中调用函数 updateViewController
。所以这是您需要更新的内容。
在ViewController中:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let secondViewController = segue.destination as! SecondViewController
secondViewController.dailyGoal = dailyGoal
secondViewController.viewController = self
}
第二个ViewController:
class SecondViewController: UIViewController {
weak var viewController: ViewController?
...
@IBAction func doneButton(_ sender: Any) {
dismiss(animated: true)
viewController?.updateViewController()
}
}
我正在学习 Swift,目前在一个项目中使用两个 ViewController。第一个控制器初始化数据并执行到第二个的 segue。第二个 ViewController 将一个新值添加到从第一个 ViewController 传入的变量中。但是,当我关闭 segue 并尝试更新第一个时,所有 IBOutlet 属性和变量突然变为 nil。这是通过在 firstViewController 的 updateViewController() 方法中记录属性得出的。提前谢谢你。
第一个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
}
}
第二个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()
}
}
您的方案要求您将 ViewController
实例传递给 SecondViewController
,而不是像您在此处所做的那样创建一个新实例。然后在完成按钮操作中调用函数 updateViewController
。所以这是您需要更新的内容。
在ViewController中:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let secondViewController = segue.destination as! SecondViewController
secondViewController.dailyGoal = dailyGoal
secondViewController.viewController = self
}
第二个ViewController:
class SecondViewController: UIViewController {
weak var viewController: ViewController?
...
@IBAction func doneButton(_ sender: Any) {
dismiss(animated: true)
viewController?.updateViewController()
}
}