Swift 将计算的数据传递回上一个视图控制器
Swift passing calculated data back to previous view controller
我正在创建我的第一个简单的预算应用程序。基本上,我需要一些用户输入,比如月收入和储蓄目标。然后他们点击 "start",应用会计算他们的每日预算等内容。
我 运行 遇到麻烦了。在所有计算之后,我显示 "how much you can spend each day"(例如每天 20 美元),我从原始屏幕上的原始输入通过 segues 向前传递。
现在,在这个 VC (UserInfoVC
) 中,我创建了一个按钮,让他们添加他们今天花了多少钱。因此,当他们单击此 "add money spent" 按钮时,我会打开一个新的 VC (AddSubtractMoney
),我会在其中显示一个计算器,他们可以在其中输入他们今天花费了多少(即 12 美元),然后单击提交。
我 运行 将他们的输入与他们的每日预算进行比较以获得新的每日预算。
现在,我无法向后传递这个更新后的数字,无法将其显示在标签 "dailySpendingLimitLabel" 上的前一个 VC 上。我知道 segues 不是向后传递数据的最佳方式。
我试过闭包,但我最终迷失了语法、协议和委托(这是我第 2 个月的编码)。
是否有一种简单的方法可以将此数据传递回之前的 VC 并在之前的显示标签中填充数据?
下面是代码。
第一个片段来自 UserInfoVC,我在其中显示了我搜索过的他们最初输入的数据。第二个片段来自 AddSubtractMoney
class,我在其中放置了计算器并在一个函数内创建了一个对象 "newestUpdate",该函数允许我计算他们在计算器上输入的数字减去他们原来的每日预算.为了得出新的预算,我想向 UserInfoVC
.
提交
class UserInfoViewController : ViewController {
var userNamePassedOver : String?
var userDailyBudgetPassedOver : Double = 99.0
var userDailySavingsPassedOver : Double = 778.00
var userMonthlyEarningsPassedOver : Double?
var userDesiredSavingsPassedOver : Double?
var newAmountPassedBack : Double = 0.0
@IBOutlet weak var dailySavingsNumberLabel: UILabel!
@IBOutlet weak var userNameLabel: UILabel!
@IBOutlet weak var dailySpendingLimitLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
userNameLabel.text = userNamePassedOver
dailySpendingLimitLabel.text = String(format: "%.2f", userDailyBudgetPassedOver)
dailySavingsNumberLabel.text = String(format: "%.2f", userDailySavingsPassedOver)
}
@IBAction func addSubtractMoneyPressed(_ sender: UIButton) {
performSegue(withIdentifier: "addOrSubtractMoney", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "addOrSubtractMoney"{
let addOrSubtractMoneyVC = segue.destination as! AddSubtractMoney
addOrSubtractMoneyVC.dailyBudgetPassedThrough = userDailyBudgetPassedOver
}
}
}
extension UserInfoViewController: AddSubtractMoneyDelegate {
func calculatedValue(value: Double) {
dailySpendingLimitLabel.text = String(userDailyBudgetPassedOver - value)
}
}
import UIKit
protocol AddSubtractMoneyDelegate {
func calculatedValue(value: Double)
}
class AddSubtractMoney: UIViewController {
@IBOutlet weak var outputLabel: UILabel!
var runningNumber = ""
var finalNumberPassedOver : Double?
var amountPassedBackToUserInfo : Double = 0.0
var dailyBudgetPassedThrough : Double = 0.0
var delegate: AddSubtractMoneyDelegate?
override func viewDidLoad() {
super.viewDidLoad()
outputLabel.text = "0"
// Do any additional setup after loading the view.
}
@IBAction func buttonPressed(_ sender: UIButton) {
runningNumber += "\(sender.tag)"
outputLabel.text = runningNumber
}
@IBAction func submitNewInfo(_ sender: UIButton) {
// FIX FIX
AddSubtractMoneyController.addToMoneySpentArray(amountISpent: outputLabel.text!)
sendBackUpdatedNumber()
dismiss(animated: true, completion: nil)
}
@IBAction func allClearedPressed(_ sender: UIButton) {
runningNumber = ""
outputLabel.text = "0"
}
// THIS LINE PRODUCES THE CORRECT INPUT IN OUTPUT CONSOLE WHEN I PRINT- BUT I CANT FIGURE HOW TO TRANSFER IT BACK TO PREVIOUS VC
func sendBackUpdatedNumber(){
let newestUpdate = UserInfo(whatYouSpentToday: runningNumber, oldDailyBudgetPassed: dailyBudgetPassedThrough)
amountPassedBackToUserInfo = dailyBudgetPassedThrough - Double(runningNumber)!
newestUpdate.goalToSaveDaily = amountPassedBackToUserInfo
print(amountPassedBackToUserInfo)
self.delegate?.calculatedValue(value: amountPassedBackToUserInfo)
}
}
使用委托
if segue.identifier == "addOrSubtractMoney" {
let addOrSubtractMoneyVC = segue.destination as! AddSubtractMoney
addOrSubtractMoneyVC.dailyBudgetPassedThrough = userDailyBudgetPassedOver
addOrSubtractMoneyVC.delegate = self
}
}
您需要在AddSubtractMoney
class
中添加delegate
属性
var delegate: AddSubtractMoneyDelegate?
在 AddSubtractMoney
class
中创建协议
protocol AddSubtractMoneyDelegate {
func calculatedValue(value: Double)
}
并回复委托
func sendBackUpdatedNumber(){
let newestUpdate = UserInfo(whatYouSpentToday: runningNumber, oldDailyBudgetPassed: dailyBudgetPassedThrough)
amountPassedBackToUserInfo = dailyBudgetPassedThrough - Double(runningNumber)!
newestUpdate.goalToSaveDaily = amountPassedBackToUserInfo
print(amountPassedBackToUserInfo)
self.delegate.calculatedValue(value: amountPassedBackToUserInfo)
}
现在您需要在 class 设置委托的地方实现此委托方法。
此处UserInfoViewController
设置了class委托,因此您需要实现其委托方法
extension UserInfoViewController: AddSubtractMoneyDelegate {
func calculatedValue(value: Double) {
//set label here
}
}
如果您不了解委托背后的流程(面向协议),您可以简单地浏览下面的代码。它只有在 class
但这不是一个好的做法
了解最常用、灵活且可重用的编码方法的协议、闭包或通知中心广播。
UserInfoViewController
class UserInfoViewController : ViewController {
fun receiveBackUpdatedNumber(numberString:String){
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "addOrSubtractMoney"{
let addOrSubtractMoneyVC = segue.destination as! AddSubtractMoney
addOrSubtractMoneyVC.userInfoViewController = self
}
}
}
}
加减钱
class AddSubtractMoney: UIViewController {
var userInfoViewController: UserInfoViewController!
var updatedNumber = ""
func sendBackUpdatedNumber(){
self.userInfoViewController.receiveBackUpdatedNumber(numberString: updatedNumber)
}
}
如果你确定可以使用协议.. 协议坚持class强制实现一个方法,这使代码更可重用和独立。
在上面的方法中,我们在执行 segue 时将当前 viewcontroller(UserInfoViewController) 的实例传递给下一个 viewcontroller(AddSubtractMoney),因此我们可以访问 [=27 中函数的任何属性=]UserInfoViewController 来自 AddSubtractMoney。所以它很容易将数据从 AddSubtractMoney 传递到 -> UserInfoViewController
我的建议是使用回调闭包。与协议/委托相比,它的代码更少,更易于处理。
在 AddSubtractMoney
中声明一个 callback
变量并在 sendBackUpdatedNumber
中调用它传递 Double
值
class AddSubtractMoney: UIViewController {
// ...
var callback : ((Double)->())?
// ...
func sendBackUpdatedNumber(){
let newestUpdate = UserInfo(whatYouSpentToday: runningNumber, oldDailyBudgetPassed: dailyBudgetPassedThrough)
amountPassedBackToUserInfo = dailyBudgetPassedThrough - Double(runningNumber)!
newestUpdate.goalToSaveDaily = amountPassedBackToUserInfo
print(amountPassedBackToUserInfo)
callback?(amountPassedBackToUserInfo)
}
}
在prepare(for segue
中将闭包分配给callback
变量并添加要在return
上执行的代码
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "addOrSubtractMoney"{
let addOrSubtractMoneyVC = segue.destination as! AddSubtractMoney
addOrSubtractMoneyVC.callback = { result in
print(result)
// do something with the result
}
addOrSubtractMoneyVC.dailyBudgetPassedThrough = userDailyBudgetPassedOver
}
}
您也可以使用 unwind segue 传回数据。
我正在创建我的第一个简单的预算应用程序。基本上,我需要一些用户输入,比如月收入和储蓄目标。然后他们点击 "start",应用会计算他们的每日预算等内容。
我 运行 遇到麻烦了。在所有计算之后,我显示 "how much you can spend each day"(例如每天 20 美元),我从原始屏幕上的原始输入通过 segues 向前传递。
现在,在这个 VC (UserInfoVC
) 中,我创建了一个按钮,让他们添加他们今天花了多少钱。因此,当他们单击此 "add money spent" 按钮时,我会打开一个新的 VC (AddSubtractMoney
),我会在其中显示一个计算器,他们可以在其中输入他们今天花费了多少(即 12 美元),然后单击提交。
我 运行 将他们的输入与他们的每日预算进行比较以获得新的每日预算。
现在,我无法向后传递这个更新后的数字,无法将其显示在标签 "dailySpendingLimitLabel" 上的前一个 VC 上。我知道 segues 不是向后传递数据的最佳方式。
我试过闭包,但我最终迷失了语法、协议和委托(这是我第 2 个月的编码)。
是否有一种简单的方法可以将此数据传递回之前的 VC 并在之前的显示标签中填充数据?
下面是代码。
第一个片段来自 UserInfoVC,我在其中显示了我搜索过的他们最初输入的数据。第二个片段来自 AddSubtractMoney
class,我在其中放置了计算器并在一个函数内创建了一个对象 "newestUpdate",该函数允许我计算他们在计算器上输入的数字减去他们原来的每日预算.为了得出新的预算,我想向 UserInfoVC
.
class UserInfoViewController : ViewController {
var userNamePassedOver : String?
var userDailyBudgetPassedOver : Double = 99.0
var userDailySavingsPassedOver : Double = 778.00
var userMonthlyEarningsPassedOver : Double?
var userDesiredSavingsPassedOver : Double?
var newAmountPassedBack : Double = 0.0
@IBOutlet weak var dailySavingsNumberLabel: UILabel!
@IBOutlet weak var userNameLabel: UILabel!
@IBOutlet weak var dailySpendingLimitLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
userNameLabel.text = userNamePassedOver
dailySpendingLimitLabel.text = String(format: "%.2f", userDailyBudgetPassedOver)
dailySavingsNumberLabel.text = String(format: "%.2f", userDailySavingsPassedOver)
}
@IBAction func addSubtractMoneyPressed(_ sender: UIButton) {
performSegue(withIdentifier: "addOrSubtractMoney", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "addOrSubtractMoney"{
let addOrSubtractMoneyVC = segue.destination as! AddSubtractMoney
addOrSubtractMoneyVC.dailyBudgetPassedThrough = userDailyBudgetPassedOver
}
}
}
extension UserInfoViewController: AddSubtractMoneyDelegate {
func calculatedValue(value: Double) {
dailySpendingLimitLabel.text = String(userDailyBudgetPassedOver - value)
}
}
import UIKit
protocol AddSubtractMoneyDelegate {
func calculatedValue(value: Double)
}
class AddSubtractMoney: UIViewController {
@IBOutlet weak var outputLabel: UILabel!
var runningNumber = ""
var finalNumberPassedOver : Double?
var amountPassedBackToUserInfo : Double = 0.0
var dailyBudgetPassedThrough : Double = 0.0
var delegate: AddSubtractMoneyDelegate?
override func viewDidLoad() {
super.viewDidLoad()
outputLabel.text = "0"
// Do any additional setup after loading the view.
}
@IBAction func buttonPressed(_ sender: UIButton) {
runningNumber += "\(sender.tag)"
outputLabel.text = runningNumber
}
@IBAction func submitNewInfo(_ sender: UIButton) {
// FIX FIX
AddSubtractMoneyController.addToMoneySpentArray(amountISpent: outputLabel.text!)
sendBackUpdatedNumber()
dismiss(animated: true, completion: nil)
}
@IBAction func allClearedPressed(_ sender: UIButton) {
runningNumber = ""
outputLabel.text = "0"
}
// THIS LINE PRODUCES THE CORRECT INPUT IN OUTPUT CONSOLE WHEN I PRINT- BUT I CANT FIGURE HOW TO TRANSFER IT BACK TO PREVIOUS VC
func sendBackUpdatedNumber(){
let newestUpdate = UserInfo(whatYouSpentToday: runningNumber, oldDailyBudgetPassed: dailyBudgetPassedThrough)
amountPassedBackToUserInfo = dailyBudgetPassedThrough - Double(runningNumber)!
newestUpdate.goalToSaveDaily = amountPassedBackToUserInfo
print(amountPassedBackToUserInfo)
self.delegate?.calculatedValue(value: amountPassedBackToUserInfo)
}
}
使用委托
if segue.identifier == "addOrSubtractMoney" {
let addOrSubtractMoneyVC = segue.destination as! AddSubtractMoney
addOrSubtractMoneyVC.dailyBudgetPassedThrough = userDailyBudgetPassedOver
addOrSubtractMoneyVC.delegate = self
}
}
您需要在AddSubtractMoney
class
delegate
属性
var delegate: AddSubtractMoneyDelegate?
在 AddSubtractMoney
class
protocol AddSubtractMoneyDelegate {
func calculatedValue(value: Double)
}
并回复委托
func sendBackUpdatedNumber(){
let newestUpdate = UserInfo(whatYouSpentToday: runningNumber, oldDailyBudgetPassed: dailyBudgetPassedThrough)
amountPassedBackToUserInfo = dailyBudgetPassedThrough - Double(runningNumber)!
newestUpdate.goalToSaveDaily = amountPassedBackToUserInfo
print(amountPassedBackToUserInfo)
self.delegate.calculatedValue(value: amountPassedBackToUserInfo)
}
现在您需要在 class 设置委托的地方实现此委托方法。
此处UserInfoViewController
设置了class委托,因此您需要实现其委托方法
extension UserInfoViewController: AddSubtractMoneyDelegate {
func calculatedValue(value: Double) {
//set label here
}
}
如果您不了解委托背后的流程(面向协议),您可以简单地浏览下面的代码。它只有在 class
但这不是一个好的做法 了解最常用、灵活且可重用的编码方法的协议、闭包或通知中心广播。
UserInfoViewController
class UserInfoViewController : ViewController {
fun receiveBackUpdatedNumber(numberString:String){
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "addOrSubtractMoney"{
let addOrSubtractMoneyVC = segue.destination as! AddSubtractMoney
addOrSubtractMoneyVC.userInfoViewController = self
}
}
}
}
加减钱
class AddSubtractMoney: UIViewController {
var userInfoViewController: UserInfoViewController!
var updatedNumber = ""
func sendBackUpdatedNumber(){
self.userInfoViewController.receiveBackUpdatedNumber(numberString: updatedNumber)
}
}
如果你确定可以使用协议.. 协议坚持class强制实现一个方法,这使代码更可重用和独立。
在上面的方法中,我们在执行 segue 时将当前 viewcontroller(UserInfoViewController) 的实例传递给下一个 viewcontroller(AddSubtractMoney),因此我们可以访问 [=27 中函数的任何属性=]UserInfoViewController 来自 AddSubtractMoney。所以它很容易将数据从 AddSubtractMoney 传递到 -> UserInfoViewController
我的建议是使用回调闭包。与协议/委托相比,它的代码更少,更易于处理。
在 AddSubtractMoney
中声明一个 callback
变量并在 sendBackUpdatedNumber
中调用它传递 Double
值
class AddSubtractMoney: UIViewController {
// ...
var callback : ((Double)->())?
// ...
func sendBackUpdatedNumber(){
let newestUpdate = UserInfo(whatYouSpentToday: runningNumber, oldDailyBudgetPassed: dailyBudgetPassedThrough)
amountPassedBackToUserInfo = dailyBudgetPassedThrough - Double(runningNumber)!
newestUpdate.goalToSaveDaily = amountPassedBackToUserInfo
print(amountPassedBackToUserInfo)
callback?(amountPassedBackToUserInfo)
}
}
在prepare(for segue
中将闭包分配给callback
变量并添加要在return
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "addOrSubtractMoney"{
let addOrSubtractMoneyVC = segue.destination as! AddSubtractMoney
addOrSubtractMoneyVC.callback = { result in
print(result)
// do something with the result
}
addOrSubtractMoneyVC.dailyBudgetPassedThrough = userDailyBudgetPassedOver
}
}
您也可以使用 unwind segue 传回数据。