tas5521 / MedicineNameQuiz

薬の名前のクイズアプリ
1 stars 0 forks source link

前回選択した時の値からスタートする #92 #105

Closed tas5521 closed 6 months ago

tas5521 commented 6 months ago

関連Issue番号

close #92

追加・変更の概要

学習画面の、問題リスト選択、および、モード選択のPickerを、前回選択した位置からスタートするようにします。

変更の目的

前回選択した位置からスタートできるとユーザーにとって便利であると思われるため。

タスクの進捗状況

変更内容

影響範囲

操作方法

  1. 問題リストを二つ作成してください。
  2. 各Pickerを初期位置から移動させてください。
  3. アプリを落としてください。
  4. アプリを再び起動して、Pickerが、前回終了した位置から再開されていることを確認してください。 PR105_1

テストしたこと

上記を確認しました。

相談事項

CoreDataに保存したいPickerの状態は3つありますが、全てsaveUserSelectionでまとめて行っています。そのため、一つのPickerの値が変わったときに、他の2つは変化がないにも関わらず、保存処理が行われてしまいます。これが問題なければ、どのPickerでもsaveUserSelectionの一つのメソッドを実行すれば良いので楽なのですが、各Pickerごとに別々の処理にした方が良いでしょうか? よろしくお願いします。

tas5521 commented 6 months ago

@YoshinoriKobayashi @FromF Pickerの状態をCoreDataではなくUserDefaultsに保存する案をくださり、ありがとうございました🙏 作成していただいたPR (#106)を参考に、コードを修正しました。 ほとんど、提供していただいた例に倣っていますが、下記の点で異なっています。

  1. ModeSelectionViewModelの拡張により追加するUserSelection構造体は、Encodable, Decodableというように分けず、Codableに準拠しました。また、questionListIDはUUID型であり、UUID型はCodableに準拠しているので、そのまま使用できるのではないかと思い、String?型ではなくUUID型にしました。 https://github.com/CodeCandySchool/MedicineNameQuiz_Sagae/blob/95ca00cd2e44df62a9e7dafec4dcd0c4b58735f0/MedicineNameQuiz_Sagae/ViewModel/ModeSelectionViewModel.swift#L109-L115

  2. userDefaultsKeyは、 settingではなく、userSelectionにしました。 https://github.com/CodeCandySchool/MedicineNameQuiz_Sagae/blob/95ca00cd2e44df62a9e7dafec4dcd0c4b58735f0/MedicineNameQuiz_Sagae/ViewModel/ModeSelectionViewModel.swift#L38-L39

  3. loadUserSelectionメソッドでは、if letのネストが深いように感じたので、guard letを使用しました。また、questionListIDはString?型ではなくUUID型にしたので、アンラップしなくなりました。 https://github.com/CodeCandySchool/MedicineNameQuiz_Sagae/blob/95ca00cd2e44df62a9e7dafec4dcd0c4b58735f0/MedicineNameQuiz_Sagae/ViewModel/ModeSelectionViewModel.swift#L91-L107

  4. ModeSelectionViewの.onAppearでは、if文の処理が消されていましたが、これは残しました。理由は、以下の操作をしたときにクラッシュしてしまうのを避けるためです。

<クラッシュする操作>

  1. 問題リストを少なくとも2つ作成する。
  2. 学習画面の問題リスト選択Pickerで、ある問題リストを選択する。
  3. 問題リスト画面に移動し、その問題リストを削除する。
  4. 学習画面に戻ってスタートを押す(該当の問題リストがないためにクラッシュしてしまう)。

このクラッシュを回避するため、指定されたIDの問題が問題リスト(fetchedLists)にない場合に、リストの一番上の問題リストをセットしています。また、この時にも選択されているPickerが変わるため、UserDefaultsへの保存を行っています。 https://github.com/CodeCandySchool/MedicineNameQuiz_Sagae/blob/95ca00cd2e44df62a9e7dafec4dcd0c4b58735f0/MedicineNameQuiz_Sagae/View/Study/ModeSelectionView.swift#L138-L153

ご検討をお願いいたします🙇‍♂️

tas5521 commented 6 months ago

@FromF ご提案をありがとうございました! UserDefaultsKeys列挙型を作成し、型から静的変数を呼び出すようにしました。 https://github.com/CodeCandySchool/MedicineNameQuiz_Sagae/blob/763364537e1c6c4172ab29829359c893dce57c60/MedicineNameQuiz_Sagae/Model/UserDefaultsKeys.swift#L10-L12 https://github.com/CodeCandySchool/MedicineNameQuiz_Sagae/blob/763364537e1c6c4172ab29829359c893dce57c60/MedicineNameQuiz_Sagae/ViewModel/ModeSelectionViewModel.swift#L83-L84

一つ気になったのですが、下記のように構造体でも可能かと思いますが、構造体でも列挙型でも、どちらでも良いのでしょうか?

    struct UserDefaultsKeys {
        static let userSelection = "userSelection"
    }

Enumの方が良い理由等がありましたら、知りたいです🙏

FromF commented 6 months ago

@tas5521

まず、wikipediaをそれぞれの定義を確認してみましょう。

今回の目的は、UserDefautlsのキーを管理する目的で提案しました。これは、とりうるキーを一元管理することだと考えていますので、有限集合となるのではないかと考えていて、そこで列挙型(enum)を選択しました。

@FromF ご提案をありがとうございました! UserDefaultsKeys列挙型を作成し、型から静的変数を呼び出すようにしました。

https://github.com/CodeCandySchool/MedicineNameQuiz_Sagae/blob/763364537e1c6c4172ab29829359c893dce57c60/MedicineNameQuiz_Sagae/Model/UserDefaultsKeys.swift#L10-L12

https://github.com/CodeCandySchool/MedicineNameQuiz_Sagae/blob/763364537e1c6c4172ab29829359c893dce57c60/MedicineNameQuiz_Sagae/ViewModel/ModeSelectionViewModel.swift#L83-L84

一つ気になったのですが、下記のように構造体でも可能かと思いますが、構造体でも列挙型でも、どちらでも良いのでしょうか?

    struct UserDefaultsKeys {
        static let userSelection = "userSelection"
    }

Enumの方が良い理由等がありましたら、知りたいです🙏