私は最初のシンプルな予算作成アプリを作成しています。基本的に、私は毎月の収入と貯蓄目標のようないくつかのユーザー入力を受け取ります。次に、「開始」をクリックすると、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)
}
}
私の提案は、コールバッククロージャーを使用することです。プロトコル/デリゲートよりもコードが少なく、処理が簡単です。
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
変数に割り当て、戻り時に実行されるコードを追加します
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
}
}
nwind segue を使用してデータを返すこともできます。
デリゲートを使用する
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
}
}
デリゲート(プロトコル指向)の背後にあるフローを理解していない場合は、単純に以下のコードを実行できます。両方のクラスの場合にのみ機能します
しかし、それは良い習慣ではありませんプロトコル、クロージャ、または通知センターのブロードキャストについて学びます。
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にデータを渡すのが簡単になります