🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
iOS

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

Xcode

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

Swift

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

iPhone

iPhoneとは、アップル社が開発・販売しているスマートフォンです。 同社のデジタルオーディオプレーヤーiPodの機能、電話機能、インターネットやメールなどのWeb通信機能の3つをドッキングした機器です。

Q&A

解決済

2回答

3051閲覧

UserDefaultsの永続化ができない

Amuy

総合スコア50

iOS

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

Xcode

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

Swift

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

iPhone

iPhoneとは、アップル社が開発・販売しているスマートフォンです。 同社のデジタルオーディオプレーヤーiPodの機能、電話機能、インターネットやメールなどのWeb通信機能の3つをドッキングした機器です。

0グッド

0クリップ

投稿2020/01/07 02:37

編集2020/01/07 04:32

前提・実現したいこと

ボールゲームを作成中です
ゲームが終了した後、ポイントが表示され、そのポイントをショップ画面で見れるように、今あるポイントにゲーム終了後にもらえるポイントを足すプログラムを作っているます。
UserDefaultsにポイントを保存させたのですが...
(Printでユーザーデフォルトの中身の値とlabelに表示させるようの変数の値を表示させています)

ポイントをもらえる画面からショップに行った時
UserDefaults 今のポイント
Label用Point 今のポイント

ショップ画面を閉じてもう一度ショップ画面を開くと
UserDefaults 0
Label用Point 今のポイント

もう一度ショップを開くと
UserDefaults 0
Label用Point 0

ポイントをもらえる画面からホーム画面に移動してからショップ画面を開いた時は
UserDefaults 0
Label用Point 0

になってしまいます...

UserDefaultsを永続化させる方法、考え方を教えてください

該当のソースコード

swift

1import UIKit 2 3class ViewControllerShop: UIViewController { 4 @IBOutlet weak var PointLabel: UILabel! 5 6 var userDefaults = UserDefaults.standard 7 var getPoint2 = 0 8 var getPointUD = 0 9 10 override func viewDidLoad() { 11 super.viewDidLoad() 12 13 saveData() 14 PointLabel.text = String(getPointUD) + " PT" 15 print("ゲットポイント" + String(getPointUD)) 16 print("ユーザーデフォルト" + String(userDefaults.integer(forKey: "DataGetPoint"))) 17} 18 19 func saveData(){ 20 getPointUD = userDefaults.integer(forKey: "DataGetPoint") 21 userDefaults.set(getPoint2, forKey: "DataGetPoint") 22 userDefaults.synchronize() 23 getPointUD = getPointUD + userDefaults.integer(forKey: "DataGetPoint") 24 } 25 26 27}

試したこと

userDefaults.synchronize()を入れるとUserDefaultsの永続化が可能だとネットで知ったので入れてみた。

データを保存し、永続化するメソッド。
データを保存した際に登場する。
よく忘れてしまうので注意が必要。

一旦UserDefaultsの値を保存するための変数getPointUDを用意した

補足情報(FW/ツールのバージョンなど)

MacBookPro2015

MacOSCatalina
10.15.2

XcodeVersion 11.2.1

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

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

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

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

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

guest

回答2

0

viewDidLoad()内でやるべきなのはsaveDataではなくloadDataなのでは??

投稿2020/01/07 05:45

takabosoft

総合スコア8356

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

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

Amuy

2020/01/07 06:06

ロードというのは、UserDefaultの値を取得する「userDefaults.integer(forKey: "DataGetPoint")」ということでしょうか?
takabosoft

2020/01/07 07:15

ですね。 UserDefaultはストレージデータと言っても良いと思いますので、 画面に入ったらストレージからメモリへポイントをロード、 なにかポイントに更新があったら、メモリからストレージへポイントをセーブ というようにプログラムを単純化したほうがいいです。
Amuy

2020/01/07 09:14

なるほど!やってみます!
Amuy

2020/01/08 09:45

解決することができました!takabosoftさん、アドバイスありがとうございました!
guest

0

ベストアンサー

ショップ画面を閉じてもう一度ショップ画面を開くと

UserDefaults 0

そういう処理になっています。

Swift

1 var getPoint2 = 0 //画面破棄→メモリ上に再展開でゼロリセット 2 override func viewDidLoad() { //メモリ上に展開されたときに呼び出される(画面破棄→再表示で発生) 3 super.viewDidLoad() 4 5 saveData() 6 ... 7 } 8 func saveData(){ 9 ... 10 userDefaults.set(getPoint2, forKey: "DataGetPoint") //ゼロで上書き 11 ... 12 }

初期化なら、"DataGetPoint"が登録済みか確認してから。

【iOS】UserDefaultsをSwiftらしく使う を参照
5 存在チェック
→初期化(登録)を実行していない場合、integer(forKey)はゼロが返ります。
6 Synchronize
→こちらはおまけ

投稿2020/01/07 05:24

編集2020/01/07 06:11
dsuzuki

総合スコア1682

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

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

Amuy

2020/01/07 05:36

回答ありがとうございます。 getPoint2には、値渡しの値が入るので消すことができません... それと、「初期化なら、"DataGetPoint"が登録済みか確認してから。」の意味を教えてください。 本当に何もわからなくてすいません...
dsuzuki

2020/01/07 06:03

回答に追記しました。
Amuy

2020/01/07 06:15 編集

チェックしてみました「if UserDefaults.standard.object(forKey: "DataGetPoint") != nil { print("nil") }」 起動するとnilと表示されました。 getPoint2が起動された時から0だとuserdefaultsも0になってしまうとのことだったので、空の変数に「var getPoint2:Int!」に切り替えましたが、それでも2回目に開くとuserdefaultsは0になってしまいます.
dsuzuki

2020/01/07 06:38

viewDidLoad内で、saveData()を実行しているのが問題です。(takabosoftさんの指摘と同じ) 何の為に、viewDidLoad内(画面表示時)で値を保存しているのでしょうか。 UserDefaultsへ保存するのは、ポイントが増えたときか、減ったとき。 ショップ画面を表示するだけで、ポイントは変わるのでしょうか。 (そういう仕様なら必要な処理ですが、その場合、getPoint2は保存すべき値になっているはずです。)
Amuy

2020/01/08 04:59

getPointUD = getPoint2 + userDefaults.integer(forKey: "DataGetPoint") PointLabel.text = String(getPointUD) + " PT" プログラムを簡略化してみましたが、一回ショップ画面を閉じてもう一度開くと、(またはホーム画面からゲームをせずにショップ画面を開くと) getPointUD = getPoint2 + userDefaults.integer(forKey: "DataGetPoint") のところに「Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value」というエラーが出てしまいました...ゲームをプレイした後にボタンを押して画面繊維した時のショップ画面では普通に開くことができます。
Amuy

2020/01/08 04:59

長文失礼しました
dsuzuki

2020/01/08 05:21

saveData()の実行タイミングは変更しましたか?(変更していないなら、なぜviewDidLoadで保存が必要?) getPoint2は、var getPoint2: Int! のまま? (getPoint2の参照時にエラーが発生しているとは思いますが) エラーが発生したとき、行だけでなく、どこが問題なのか示されているはずです。 そこから、どの変数(もしくはメソッド)の何が問題なのか理解することが必要です。 今回は、nilをアンラップしようとしているのが問題です。
Amuy

2020/01/08 05:30

savedata()はコメントアウトしました。getPoint2はvar getPoint2: Int!ままです...それと、 if UserDefaults.standard.object(forKey: "DataGetPoint") != nil { print("nil") getPoint2 = 0 } のプログラムもコメントアウトしました
dsuzuki

2020/01/08 05:58

> getPoint2はvar getPoint2: Int!ままです この場合、getPoint2の初期値は、nil です。 何も値を設定しないまま、参照すれば問題のエラーが発生します。 元々は、userdefaultsへゼロで保存していたのが問題であり、getPoint2 の初期値ゼロが問題ではありません。 saveData()をコメントアウトしたのなら、 var getPoint2 = 0 に戻すことで解決しませんか。
Amuy

2020/01/08 09:34

なるほど!そういうことだったんですね!やってみます
Amuy

2020/01/08 09:38

今回はホーム画面からショップを開いても落ちませんでしたが、 ゲットポイント もらったポイント ユーザーデフォルト 0 になってしまいました...UserDefaultsに保存してないからですかね...
Amuy

2020/01/08 09:43

getPointUD = getPoint2 + userDefaults.integer(forKey: "DataGetPoint") UserDefaults.standard.set(getPointUD, forKey: "DataGetPoint") PointLabel.text = String(getPointUD) + " PT" このプログラムにしたらうまくいきました!
Amuy

2020/01/08 09:44

長くお付き合い&アドバイスありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問