繁体   English   中英

Swift 将计算出的数据传回之前的视图控制器

[英]Swift passing calculated data back to previous view controller

我正在创建我的第一个简单的预算应用程序。 基本上,我会接受一些用户输入,例如月收入和储蓄目标。 然后他们点击“开始”,应用程序会计算诸如他们的每日预算等内容。

在这里,我遇到了麻烦。 在所有计算之后,我会显示“您每天可以花多少钱”(例如每天 20 美元),我将这些信息从原始屏幕上的原始输入中通过 segue 传递出去。

现在,在这个 VC ( UserInfoVC ) 中,我创建了一个按钮,让他们添加今天花了多少钱。 因此,当他们点击这个“添加花费的钱”按钮时,我打开一个新的 VC ( AddSubtractMoney ),我在其中展示了一个计算器,他们可以在其中输入他们今天花费的金额(即 12 美元),然后单击提交。

我将他们的输入与他们的每日预算进行比较以获得新的每日预算。

现在,我无法向后传递这个更新的数字,以在标签“dailySpendingLimitLabel”上的前一个 VC 上显示它。 我知道转场不是向后传递数据的最佳方式。

我尝试过闭包,但最终我迷失在语法、协议和委托中(这是我第二个月的编码)。

有没有一种简单的方法来实现将这些数据传递回之前的 VC 并在之前的显示标签中填充数据?

下面是代码。

第一个片段来自 UserInfoVC,我在其中显示了他们最初输入的我通过的数据。 第二个片段来自AddSubtractMoney类,我在其中放置了计算器并在一个函数中创建了一个对象“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)


}


}

我的建议是使用回调闭包。 与协议/委托相比,它的代码更少且更易于处理。

AddSubtractMoney声明一个callback变量并在传递Double值的sendBackUpdatedNumber调用它

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变量并添加要在返回时执行的代码

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
    }
}

使用委托

if segue.identifier == "addOrSubtractMoney" {

    let addOrSubtractMoneyVC = segue.destination as! AddSubtractMoney

        addOrSubtractMoneyVC.dailyBudgetPassedThrough = userDailyBudgetPassedOver

       addOrSubtractMoneyVC.delegate = self
    }
}

您需要在AddSubtractMoney类中添加delegate属性

var delegate: AddSubtractMoneyDelegate?

AddSubtractMoney类中创建协议

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)
}

现在您需要在设置了委托的类中实现这个委托方法。

这里在UserInfoViewController类中设置了委托,因此您需要实现其委托方法

extension UserInfoViewController: AddSubtractMoneyDelegate {

  func calculatedValue(value: Double) {

       //set label here
  } 

}

您也可以使用unwind segue来传回数据。

如果您不了解委托背后的流程(面向协议),您可以简单地通过以下代码。 它只有在两个类时才有效

但这不是一个好的做法了解协议、闭包或通知中心广播以了解最常用的、灵活的和可重用的编码方法。

用户信息视图控制器

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)
   }
}

如果你确定,你可以使用协议。协议坚持一个类来强制实现一个方法,这使得代码更可重用和独立。

在上面的方法中,我们在执行 segue 时将当前视图控制器(UserInfoViewController)的实例传递给下一个视图控制器(AddSubtractMoney),因此我们可以从AddSubtractMoney访问UserInfoViewController中函数的任何属性。 所以很容易将数据从 AddSubtractMoney 传递到 -> UserInfoViewController

暂无
暂无

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

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