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

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

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

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

Q&A

解決済

1回答

867閲覧

Swift:UserDefaultsを読み込んだ際に値がnilになる

toyu

総合スコア11

Swift

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

0グッド

0クリップ

投稿2022/05/09 03:29

前提

Swiftを独学で勉強し始めて1ヶ月ほどの初心者です。
家計簿のアプリを作成しています。
データを保存するためにUserDefaultsを使用して、MyData クラスを保存しています。
セクション名をMyDataクラスのインスタンス変数から読み取って使用しています。

発生している問題・エラーメッセージ

アプリ再起動時にUserDefaultsに保存されているMyDataクラスのインスタンス変数を読み込もうとすると、値が nil になっており、セクションを表示することができません。

UserDefaults呼び出し直後に値を読み込んでいることが問題なのかなと考えています。どのように改善するのが良いのでしょうか?

再起動前の画面

イメージ説明

再起動時の画面

イメージ説明

試したこと

tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? にて、戻り値の確認を行いました。

再起動時の出力結果 *** nil *** nil *** nil *** nil *** nil *** nil

再起動時の画面の状態から新たに同じセクションのデータを追加した場合、正しくセクションが追加されます。(データの追加は他クラスからsaveDataメソッドを呼び出しています)

再起動時の画面に5/8のデータを追加

イメージ説明

データ追加時の出力結果 *** nil *** Optional("2022-05-08") *** Optional("2022-05-08") *** Optional("2022-05-08") *** nil *** nil *** nil *** nil

該当のソースコード

Swift

1import UIKit 2 3//UITableViewDataSource、UITableViewDelegate、DataSaveプロトコルを使用 4class SecondViewController: UIViewController, UITableViewDataSource, 5 UITableViewDelegate, DataSave { 6 7 // MyDataを格納した配列 8 var mydataList = [[MyData]]() 9 // セクション名を格納した配列 10 var sectionList: [String] = [] 11 12 @IBOutlet weak var tableView: UITableView! 13 14 override func viewDidLoad() { 15 super.viewDidLoad() 16 17 //let appDomain = Bundle.main.bundleIdentifier 18 //UserDefaults.standard.removePersistentDomain(forName: appDomain!) 19 20 let userDefaults = UserDefaults.standard 21 // 保存しているsectionListを読み込み 22 if let sectionMyList = userDefaults.array(forKey: "sectionList") as? [String] { 23 sectionList = sectionMyList 24 } 25 // 保存しているMyDataの読み込み 26 if let MyList = userDefaults.object(forKey: "mydataList") as? Data { 27 do { 28 if let appendList = try NSKeyedUnarchiver.unarchivedObject(ofClasses: [NSArray.self, MyData.self], from: MyList) as? [[MyData]] { 29 mydataList.append(contentsOf: appendList) 30 } 31 } catch { 32 // エラー処理なし 33 } 34 } 35 } 36 37 38 39 40 // 入力されたデータをMyDataに保存するメソッド 41 func saveData(_ price: Int, _ tag: String, _ date: String, _ content: String, _ value: Int) { 42 43 let mydata = MyData() 44 mydata.price = price 45 mydata.tag = tag 46 mydata.date = date 47 mydata.content = content 48 mydata.segmented_value = value 49 50 var index: Int = 0 51 52 // 一致するデータが存在するか確認 53 let result = sectionList.firstIndex(of: mydata.date!) 54 55 /* ***日付を参照し、データの挿入場所を決定する*** */ 56 if result == nil { 57 // 挿入場所を表す変数 58 var insertNum: Int = 0 59 60          省略 61 62 index = insertNum 63 } 64 /* ***日付を参照し、インデクスを取得*** */ 65 else { 66 index = result! 67 } 68 69 70 // 追加 71 if result == nil { 72 self.mydataList.insert([MyData](), at: index) 73 } 74 self.mydataList[index].insert(mydata, at: 0) 75 // テーブルに行が追加されたことをテーブルに通知 76 if result == nil { 77 self.tableView.insertSections(IndexSet(integer: index), with: .automatic) 78 } 79 else{ 80 self.tableView.insertRows(at: [IndexPath(row: 0, section: index)], with: .automatic) 81 } 82 // MyDataの保存処理 83 let userDefaults = UserDefaults.standard 84 userDefaults.set(sectionList, forKey: "sectionList") 85 // Data型にシリアライズ 86 do { 87 let data = try NSKeyedArchiver.archivedData(withRootObject: self.mydataList, requiringSecureCoding: true) 88 userDefaults.set(data, forKey: "mydataList") 89 userDefaults.synchronize() 90 } catch { 91 // エラー処理なし 92 } 93 } 94 95 // セクション数を返却するメソッド 96 func numberOfSections(in tableView: UITableView) -> Int { 97 return sectionList.count 98 } 99 100 // セクションに対してセル数を返却するメソッド 101 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{ 102 return mydataList[section].count 103 104 } 105 106 // セクションに対してセクション名を返却するメソッド 107 func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { 108 109 print("***") 110 print(mydataList[section][0].date) 111 112 if let title = mydataList[section][0].date { 113 return title } 114 return nil 115 } 116 117 // テーブルの行ごとのセルを返却する 118 func tableView(_ tableView: UITableView, 119 cellForRowAt indexPath: IndexPath) -> UITableViewCell { 120 121     省略 122 123 return cell 124 } 125 126 127} 128 129// 独自クラスをシリアライズする際には、NSObjectを継承し 130// NSSecureCodingプロトコルに準拠する必要がある 131class MyData: NSObject, NSSecureCoding { 132 133 static var supportsSecureCoding: Bool { 134 return true 135 } 136 137 // インスタンス変数の宣言 138 var price: Int = 0 139 var tag: String? 140 var date: String? 141 var content: String? 142 var segmented_value: Int = 0 143 144 // コンストラクタ 145 override init() { 146 } 147 // デコード処理 148 required init?(coder aDecoder: NSCoder) { 149 price = aDecoder.decodeInteger(forKey: "price") 150 tag = aDecoder.decodeObject(forKey: "tag") as? String 151 date = aDecoder.decodeObject(forKey: "date") as? String 152 content = aDecoder.decodeObject(forKey: "content") as? String 153 segmented_value = aDecoder.decodeInteger(forKey: "segmented_value") 154 } 155 // エンコード処理 156 func encode(with aCoder: NSCoder) { 157 aCoder.encode(price, forKey: "price") 158 aCoder.encode(tag, forKey: "tag") 159 aCoder.encode(date, forKey: "data") 160 aCoder.encode(content, forKey: "content") 161 aCoder.encode(segmented_value, forKey: "segmented_value") 162 } 163} 164 165

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

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

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

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

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

guest

回答1

0

自己解決

tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? の戻り値を変更したら解決しました。
変更前:mydataList[section][0].date
変更後:sectionList[section]

投稿2022/05/09 12:43

toyu

総合スコア11

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

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

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

質問する

関連した質問