質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

保存

保存(save)とは、特定のファイルを、ハードディスク等の外部記憶装置に記録する行為を指します。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

1回答

839閲覧

UserDefaultsで保存された値を削除する方法が分からない

uma02

総合スコア18

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

保存

保存(save)とは、特定のファイルを、ハードディスク等の外部記憶装置に記録する行為を指します。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2020/07/24 01:06

編集2020/07/24 04:01

前提・実現したいこと

swiftです。やりたいこととしては、TextFieldから数字を入力するとその数字が足されて、Labelに合計値が表示され、取り消しbuttonを押すと、直前に入力された数字を削除するというものです。

どのようなコードを付け足せばいいのでしょうか。教えていただければ幸いです。

写真の左側がViewController,右側がaddViewControllerです。
addイメージ説明

ViewController import UIKit class addViewController: UIViewController { @IBOutlet weak var label: UILabel! override func viewDidLoad() { super.viewDidLoad() } // ViewControllerを開く度に中の処理が呼ばれる override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) // UserDefaultsに保存された数字が無いか確認する if let _ = UserDefaults.standard.object(forKey: "textKey") as? String { // UserDefaultsに保存されたaTextの値をlabelに表示する label.text = (UserDefaults.standard.object(forKey: "textKey") as! String) //アプリ再起動後もaddViewControllerで引き続き計算出来るように、labelに表示されている値をUserDefaultsにtext2Keyとして保存する。 UserDefaults.standard.set(Int(label.text!), forKey: "text2Key") } } @IBAction func torikesi(_ sender: Any) { UserDefaults.standard.removeObject(forKey: "textKey") } }
ViewController import UIKit // 初期値を0に設定した変数aTextを作成 var aText:Int = 0 class ViewController: UIViewController { @IBOutlet weak var label: UILabel! @IBOutlet weak var textField: UITextField! override func viewDidLoad() { super.viewDidLoad() // textFieldの入力方法をナンバーパッドに設定 textField.keyboardType = UIKeyboardType.numberPad } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) let rgba = UIColor(red: 50/255.0, green: 150/255.0, blue: 1.0, alpha: 1.0)//rgbaを定義 label.backgroundColor = rgba // 背景色 label.textColor = UIColor.white // 文字色 label.layer.cornerRadius = 10.0 // 角丸のサイズ label.clipsToBounds = true // labelの時は必須(角丸) label.layer.borderWidth = 0.0 // 枠線の幅(0なので表示なし) label.layer.borderColor = UIColor.white.cgColor // 枠線の色 // addViewControllerを開く度にViewControllerのviewDidAppearでUserDefaultsで保存したlabelの値がある場合は、aTextに反映させてaddButton内で引き続き計算出来る様にする。 if let _ = UserDefaults.standard.object(forKey: "text2Key") as? Int { aText = (UserDefaults.standard.object(forKey: "text2Key") as! Int) } } @IBAction func addButton(_ sender: Any) { // iBにtextFieldに入力された数字を入れる guard let iB = Int(textField.text!) else { return } // aTextにiBの数字を入れて、aTextに入れる。 aText = aText + iB // UserDefaultsにaTextの値をtextKeyで保存する UserDefaults.standard.set(String(aText), forKey: "textKey") } }

試したこと

削除はできているけどLabelに表示できていないだけかと思ったので、
UserDefaults.standard.removeObject(forKey: "textKey")の後に
if let _ = UserDefaults.standard.object(forKey: "textKey") as? String {
label.text = (UserDefaults.standard.object(forKey: "textKey") as! String)
UserDefaults.standard.set(Int(label.text!), forKey: "text2Key")

というコードを付け足してみましたがダメでした。

###追記
直前に入力された値を削除する際にuserdefaultsを削除するのではなく、引き算を使うように修正しました。

//ViewController import UIKit class addViewController: UIViewController { @IBOutlet weak var label: UILabel! override func viewDidLoad() { super.viewDidLoad() } // ViewControllerを開く度に中の処理が呼ばれる override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) // UserDefaultsに保存された数字が無いか確認する if let _ = UserDefaults.standard.object(forKey: "textKey") as? String { // UserDefaultsに保存されたaTextの値をlabelに表示する label.text = (UserDefaults.standard.object(forKey: "textKey") as! String) //アプリ再起動後もaddViewControllerで引き続き計算出来るように、labelに表示されている値をUserDefaultsにtext2Keyとして保存する。 UserDefaults.standard.set(Int(label.text!), forKey: "text2Key") } } @IBAction func torikesi(_ sender: Any) { guard let iB = Int(textField.text!) else { return } // aTextにiBの数字を入れて、aTextに入れる。 aText = aText - iB // UserDefaultsにaTextの値をtextKeyで保存する UserDefaults.standard.set(String(aText), forKey: "textKey") } }

###エラー
「guard let iB = Int(textField.text!) else {」のところで「Use of unresolved identifier 'textField'」というエラーが出ました。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

TsukubaDepot

2020/07/24 01:33

2つのViewController(ViewControllerとaddViewController)の関係はどのようになっているのでしょうか(遷移する関係なのか、まったく別のアプリなのか)。 また、ソースコードはそのままでは見にくいので、ご質問を編集し、コードを選択して<CODE>ボタンを押すか、```で囲むなどしていただけないでしょうか。
uma02

2020/07/24 02:21

ご指摘ありがとうございます。修正させていただきました。
TsukubaDepot

2020/07/24 02:26

ありがとうございます。かなりみやすくなりました。 ちなみに、画面遷移はボタンを押すと実行される(ボタンからSegueが張られている)という認識で大丈夫でしょうか。
uma02

2020/07/24 02:40

そうです!
TsukubaDepot

2020/07/24 02:46

「決定」ボタンにSegueを設定しているのでしょうか。 そうだとすると、決定ボタンを押した瞬間に次の画面に移動するので、複数の数字を合計させることはできないと思うのですが、その辺りはどのような流れを考えていらっしゃるのでしょうか。
uma02

2020/07/24 03:02

はい、「決定」ボタンにSegueを設定しています。今のプログラムでも数字を入力して決定ボタンを押せば、合計値に加算することはできています。 また、この方法については以下のサイトのコードを使用しました。 https://teratail.com/questions/177083
TsukubaDepot

2020/07/24 03:09

実際に実行してみているのですが、 ViewController -> 数字を入力し、ボタンを押す addViewController -> いままで入力された数値との合計を表示する 違う数字を加算する場合には、addViewController をしたにスワイプ(iOS13の場合)して表示を消し、再度数字を入力する。もしくはアプリを起動しなおす、という流れしかないはずなのですが、これが考えられている仕様でしょうか。 あと、参考にされているコードですが、残念ながらかなり参考にならないコードです。
uma02

2020/07/24 03:13

はい、その仕様であっています。 ということはsegueではなくコードを記述して遷移させた方がいいのでしょうか?
TsukubaDepot

2020/07/24 03:19

いや、Segueでもできると思います(正確には、「ボタンと直接関連づけられたSegue」)。 となると次に疑問なのは、 「Labelに合計値が表示され、取り消しbuttonを押すと、直前に入力された数字を削除するというものです。 」 という仕様です。 これは、 1. たとえばこれまでの合計が200円、直前の画面で140円入力し、次の画面では340円と表示されたが、ボタンを押すことで直前の140円をキャンセルしたい 2. 次の画面では340円と表示されたが、ボタンを押すことで合計をクリアしたい(0にしたい) のどちらになるのでしょうか。
uma02

2020/07/24 03:23

分かりにくくてすみません。 1の方でお願いします。
TsukubaDepot

2020/07/24 03:27

その流れであれば、合計額から直前の加算額を引いて保存しなおせば良く、無理にいままで保存したデータを削除する必要はないかと思いますが、いかがでしょうか。 いままで保存したオブジェクトを削除したい、という話だったので、本当は 2. の方なのかな?と疑問に思った次第です。
uma02

2020/07/24 03:49

ありがとうございます、引き算を使いたいと思います。 以下のコードをViewControllerに加えたのですが「guard let iB = Int(textField.text!)」のところでエラーが出ます。どう修正すればいいのでしょうか。基礎的なことばかり聞いてしまって申し訳ないのですがよろしくお願いします。 @IBAction func Button(_ sender: Any) { guard let iB = Int(textField.text!) else { return } // aTextにiBの数字を入れて、aTextに入れる。 aText = aText - iB UserDefaults.standard.set(String(aText), forKey: "textKey")
TsukubaDepot

2020/07/24 03:51

では、全体的な流れもみたいので、今回追加された文を含めて、ソースコード全文をご質問に追記していただけますでしょうか(他の方も分かるように、いままでのソースコードは残して、末尾に追記していただければと思います)。 ちなみに、どのようなエラーが出たのでしょうか。それも追記していただければと思います。
uma02

2020/07/24 04:01

修正させていただきました。よろしくお願いします。
guest

回答1

0

ベストアンサー

「guard let iB = Int(textField.text!) else {」のところで「Use of unresolved identifier 'textField'」というエラーが出ました。

とありますが、該当するのは次の処理だと思います。

Swift

1 @IBAction func torikesi(_ sender: Any) { 2 guard let iB = Int(textField.text!) else { 3 return 4 }

ここで textField を参照していますが、この textFieldaddViewController で定義されておらず、ViewController で定義したものなので、直接見ることはできません。

方法はいくつかあるのですが(そのうちひとつは ViewController のインスタンスを直接参照する方法)、UserDefaults を使っているため、それで統一したいと思います。

考え方としては、

  1. ViewController では追加したい値を入力し、その値を保存する
  2. addViewController でこれまでの合計と前の画面で保存された値を呼び出し、足し算を行い表示
  3. 新しい合計値を保存しなおす。
  4. 「取り消し」ボタンが押された場合は、前画面で入力された値を合計から引き、新たに保存しなおす

という流れが一つかと思います。

その流れでつくるとこのような感じになるかと思います。

Swift

1import UIKit 2 3// MARK: 削除 - グローバル変数として定義しない。また、変数名は何の目的かわかるようにする 4// 初期値を0に設定した変数aTextを作成 5//var aText:Int = 0 6 7class ViewController: UIViewController { 8 9 @IBOutlet weak var label: UILabel! 10 11 @IBOutlet weak var textField: UITextField! 12 13 // MARK: 変更 - 合計値を入れる変数。ただし、ViewController では使わないので宣言する必要はない 14 // var total = 0 15 16 override func viewDidLoad() { 17 super.viewDidLoad() 18 19 // textFieldの入力方法をナンバーパッドに設定 20 textField.keyboardType = UIKeyboardType.numberPad 21 } 22 23 override func viewDidAppear(_ animated: Bool) { 24 super.viewDidAppear(animated) 25 26 // MARK: 下記の処理はUI部品に関する処理だが、 viewDidAppear(_:) は UI部品が表示された「後」の処理なので、できれば viewWillAppear(_:) に入れる 27 let rgba = UIColor(red: 50/255.0, green: 150/255.0, blue: 1.0, alpha: 1.0)//rgbaを定義 28 label.backgroundColor = rgba // 背景色 29 label.textColor = UIColor.white // 文字色 30 label.layer.cornerRadius = 10.0 // 角丸のサイズ 31 label.clipsToBounds = true // labelの時は必須(角丸) 32 33 label.layer.borderWidth = 0.0 // 枠線の幅(0なので表示なし) 34 label.layer.borderColor = UIColor.white.cgColor // 枠線の色 35 36 // MARK: 変更 - UserDefaults から指定されたキーで Int 型を取り出すのであれば、直接取り出す。 37 // ただし、ここでは合計値を直接使う必要性はないので取り出さない 38 // total = UserDefaults.standard.integer(forKey: "合計") 39 40 } 41 42 @IBAction func addButton(_ sender: Any) { 43 // iBにtextFieldに入力された数字を入れる 44 guard let iB = Int(textField.text!) else { 45 return 46 } 47 // MARK: 変更 - ここでは引き算しない 48 // aTextにiBの数字を入れて、aTextに入れる。 49 // aText = aText + iB 50 51 // UserDefaultsにaTextの値をtextKeyで保存する 52 // MARK: 変更 - Int型なので Int型 として保存する 53 // UserDefaults.standard.set(String(aText), forKey: "textKey") 54 UserDefaults.standard.set(iB, forKey: "入力値") 55 } 56}

Swift

1import UIKit 2class addViewController: UIViewController { 3 4 @IBOutlet weak var label: UILabel! 5 6 // MARK: 前画面での入力値 7 var addNum = 0 8 // MARK: これまでの合計 9 var total = 0 10 11 override func viewDidLoad() { 12 super.viewDidLoad() 13 14 // MARK: 追加 - これまでの合計と、ViewController で入力された値を取り出す 15 16 // これまでの合計 17 // Int型で保存した値は Int 型として取り出す 18 total = UserDefaults.standard.integer(forKey: "合計") 19 // ViewController で入力された値 20 addNum = UserDefaults.standard.integer(forKey: "入力値") 21 22 // 合計を計算し、ラベルに表示 23 total += addNum 24 label.text = String(total) 25 26 // アプリ再起動時に必要なのは合計値だけなので、合計値だけ改めて保存する 27 UserDefaults.standard.set(total, forKey: "合計") 28 } 29 30 // ViewControllerを開く度に中の処理が呼ばれる 31 override func viewDidAppear(_ animated: Bool) { 32 super.viewDidAppear(animated) 33 34 // MARK: 削除 - UILabel に表示する処理は viewDidLoad に入れる(チラつき防止のため) 35 } 36 37 // MARK: 変更 - 取り消しの処理 38 @IBAction func torikesi(_ sender: Any) { 39 // 合計から ViewController で入力された値を引く 40 total -= addNum 41 // ラベルを更新する 42 label.text = String(total) 43 // 合計を保存しなおす 44 UserDefaults.standard.set(total, forKey: "合計") 45 // 必要であれば、addNumをゼロクリアする 46 // addNum = 0 47 } 48}

もちろん、このままでは色々と使いづらいところもありますが、そこは質問者さんが検討し変更すべき点だと思いますので、是非改良していただければと思います。

投稿2020/07/24 04:55

TsukubaDepot

総合スコア5086

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

uma02

2020/07/24 05:49

無事機能しました。いろいろ教えていただき本当にありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問