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

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

ただいまの
回答率

87.96%

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

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 307

score 7

前提・実現したいこと

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'」というエラーが出ました。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • uma02

    2020/07/24 12: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 12:51

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

    キャンセル

  • uma02

    2020/07/24 13:01

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

    キャンセル

回答 1

checkベストアンサー

0

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

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

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

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

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

考え方としては、

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

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

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

import UIKit

// MARK: 削除 - グローバル変数として定義しない。また、変数名は何の目的かわかるようにする
// 初期値を0に設定した変数aTextを作成
//var aText:Int = 0

class ViewController: UIViewController {

    @IBOutlet weak var label: UILabel!

    @IBOutlet weak var textField: UITextField!

    // MARK: 変更 - 合計値を入れる変数。ただし、ViewController では使わないので宣言する必要はない
    // var total = 0

    override func viewDidLoad() {
        super.viewDidLoad()

        // textFieldの入力方法をナンバーパッドに設定
        textField.keyboardType = UIKeyboardType.numberPad
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        // MARK: 下記の処理はUI部品に関する処理だが、 viewDidAppear(_:) は UI部品が表示された「後」の処理なので、できれば viewWillAppear(_:) に入れる
        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 // 枠線の色

        // MARK: 変更 - UserDefaults から指定されたキーで Int 型を取り出すのであれば、直接取り出す。
        // ただし、ここでは合計値を直接使う必要性はないので取り出さない
        //        total = UserDefaults.standard.integer(forKey: "合計")

    }

    @IBAction func addButton(_ sender: Any) {
        // iBにtextFieldに入力された数字を入れる
        guard let iB = Int(textField.text!) else {
            return
        }
        // MARK: 変更 - ここでは引き算しない
        // aTextにiBの数字を入れて、aTextに入れる。
        // aText = aText + iB

        // UserDefaultsにaTextの値をtextKeyで保存する
        // MARK: 変更 - Int型なので Int型 として保存する
        // UserDefaults.standard.set(String(aText), forKey: "textKey")
        UserDefaults.standard.set(iB, forKey: "入力値")
    }
}
import UIKit
class addViewController: UIViewController {

    @IBOutlet weak var label: UILabel!

    // MARK: 前画面での入力値
    var addNum = 0
    // MARK: これまでの合計
    var total = 0

    override func viewDidLoad() {
        super.viewDidLoad()

        // MARK: 追加 - これまでの合計と、ViewController で入力された値を取り出す

        // これまでの合計
        // Int型で保存した値は Int 型として取り出す
        total = UserDefaults.standard.integer(forKey: "合計")
        // ViewController で入力された値
        addNum = UserDefaults.standard.integer(forKey: "入力値")

        // 合計を計算し、ラベルに表示
        total += addNum
        label.text = String(total)

        // アプリ再起動時に必要なのは合計値だけなので、合計値だけ改めて保存する
        UserDefaults.standard.set(total, forKey: "合計")
    }

    // ViewControllerを開く度に中の処理が呼ばれる
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        // MARK: 削除 - UILabel に表示する処理は viewDidLoad に入れる(チラつき防止のため)
    }

    // MARK: 変更 - 取り消しの処理
    @IBAction func torikesi(_ sender: Any) {
        // 合計から ViewController で入力された値を引く
        total -= addNum
        // ラベルを更新する
        label.text = String(total)
        // 合計を保存しなおす
        UserDefaults.standard.set(total, forKey: "合計")
        // 必要であれば、addNumをゼロクリアする
        // addNum = 0
    }
}

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/07/24 14:49

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

    キャンセル

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

  • ただいまの回答率 87.96%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る