web-dev-qa-db-ja.com

Swift計算されたデータを前のビューコントローラに渡す

私は最初のシンプルな予算作成アプリを作成しています。基本的に、私は毎月の収入と貯蓄目標のようないくつかのユーザー入力を受け取ります。次に、「開始」をクリックすると、1日の予算などが計算されます。

ここで問題が発生しています。すべての計算の後、「1日あたりの費用」(たとえば、1日20ドル)を表示します。これは、元の画面の元の入力からのセグエを通過します。

さて、このVC(UserInfoVC)で、彼らが今日費やした金額を追加できるボタンを作成しました。したがって、この「使用した金額を追加」ボタンをクリックすると、新しいVC(AddSubtractMoney)を開きます。ここで、今日費やした金額(つまり$ 12)を入力して[送信]をクリックできる計算機を提示します。

新しい1日の予算を取得するために、1日の予算と比較して入力を実行します。

現在、この更新された数値を逆方向に渡して、以前のVCラベル "dailySpendingLimitLabel"に表示するために)渡すのに問題があります。 。

クロージャーを試しましたが、構文、プロトコル、デリゲートで迷子になってしまいました(2か月目のコーディングです)。

このデータを以前のVCに戻し、その以前の表示ラベルにデータを入力するための簡単な方法はありますか?

以下はコードです。

最初のスニペットは、最初に入力したデータを表示したUserInfoVCからのものです。 2番目のスニペットはAddSubtractMoneyクラスからのもので、電卓を配置し、電卓に入力した数から古い1日の予算を差し引いて計算できるようにする関数内に「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)


}


}

私の提案は、コールバッククロージャーを使用することです。プロトコル/デリゲートよりもコードが少なく、処理が簡単です。

AddSubtractMoneycallback変数を宣言し、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変数に割り当て、戻り時に実行されるコードを追加します

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

nwind segue を使用してデータを返すこともできます。

2
Balázs Vincze

デリゲートを使用する

if segue.identifier == "addOrSubtractMoney" {

    let addOrSubtractMoneyVC = segue.destination as! AddSubtractMoney

        addOrSubtractMoneyVC.dailyBudgetPassedThrough = userDailyBudgetPassedOver

       addOrSubtractMoneyVC.delegate = self
    }
}

delegateクラスにAddSubtractMoneyプロパティを追加する必要があります

var delegate: AddSubtractMoneyDelegate?

AddSubtractMoneyクラスにプロトコルを作成

protocol AddSubtractMoneyDelegate {
  fun 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
  } 

}
2
Mahendra

デリゲート(プロトコル指向)の背後にあるフローを理解していない場合は、単純に以下のコードを実行できます。両方のクラスの場合にのみ機能します

しかし、それは良い習慣ではありませんプロトコル、クロージャ、または通知センターのブロードキャストについて学びます。

serInfoViewController

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

   }
 }

AddSubtractMoney

class AddSubtractMoney: UIViewController {
  var userInfoViewController: UserInfoViewController!
  var updatedNumber = ""
  func sendBackUpdatedNumber(){
    self.userInfoViewController.receiveBackUpdatedNumber(numberString: updatedNumber)
   }
}

プロトコルに問題がある場合は、プロトコルを使用できます。プロトコルは、クラスにメソッドの強制的な実装を要求します。これにより、コードの再利用性と独立性が向上します。

上記のメソッドでは、セグエの実行時に現在のviewcontroller(UserInfoViewController)のインスタンスを次のviewcontroller(AddSubtractMoney)に渡しています。そのため、serInfoViewControllerの関数のプロパティにアクセスできます。 AddSubtractMoney。したがって、AddSubtractMoneyから-> UserInfoViewControllerにデータを渡すのが簡単になります

0
Britto Thomas