前提・実現したいこと
NextViewControllerで構造体をUserDefaults.standardに保存したのですが、保存したものをViewControllerで利用したいです。
構造体にtodo(Stringa型)とrate(Int型)を保存しており、
これをViewControllerへ渡して、TableViewのCellで利用したいです。
TODOリストにレーティング機能がついたようなアプリを作成しており、
rate == 1のときに、入力したテキスト(todo)をセクション1(heart1)へ反映させる、
rate == 1のときに、入力したテキスト(todo)をセクション1(heart2)へ反映させる、といった形で動かしたいと考えております。
やったこと
ViewControllerで利用しようとすると、エラーが出てしまいます。
let heart1 = UserDefaults.standard.data(forKey:"DoneStructList")!.filter {$0.rate==1
}
→ これを入れるとエラーが出てしまいます。
エラーコード
Value of type 'Data.Element' (aka 'UInt8') has no member 'rate'
該当のソースコード
swift
1 2struct DoneStructList: Codable { 3 4 var list = [DoneStruct]() 5 6 struct DoneStruct: Codable{ 7 8 var todo = String() 9 var rate = Int() 10 11 } 12} 13 14 15class NextViewController: UIViewController { 16 17 18 private var list: [DoneStructList.DoneStruct] = [] 19 20 var rate = 0 21 22 @IBOutlet weak var TextField: UITextField! 23 @IBOutlet weak var Label: UILabel! 24 @IBOutlet weak var heart1: UIButton! 25 @IBOutlet weak var heart2: UIButton! 26 @IBOutlet weak var heart3: UIButton! 27 @IBOutlet weak var heart4: UIButton! 28 @IBOutlet weak var heart5: UIButton! 29 30 let heartFill = UIImage(named: "heart") 31 let heartEmpty = UIImage(named: "emptyheart") 32 33 override func viewDidLoad() { 34 super.viewDidLoad() 35 36 list = getValue() ?? [] 37 38 } 39 40 41 @IBAction func AddButton(_ sender: Any) { 42 43 //配列listの中にある構造体todo,rateそれぞれにTextField.textとrateを保存する。 44 let doneStruct = DoneStructList.DoneStruct(todo: TextField.text!,rate: rate) 45 list.append(doneStruct) 46 save(list: list) 47 48 dismiss(animated: true, completion: nil) 49 } 50 51 //構造体を UserDefaultsへ保存するためにデータ型にエンコード 52 private func serialize(doneStructList:DoneStructList) -> Data?{ 53 do{ 54 let encoder = JSONEncoder() 55 return try 56 encoder.encode(doneStructList) 57 }catch { 58 return nil 59 } 60 } 61 62 //データ型からデコード 63 private func processJson(data: Data) -> [DoneStructList.DoneStruct]? { 64 do { 65 let jsonDecoder = JSONDecoder() 66 let doneStructList = try 67 jsonDecoder.decode(DoneStructList.self,from: data) 68 return doneStructList.list 69 }catch { 70 return nil 71 } 72 } 73 74 //UserDefaultsに保存 75 private func save(list: [DoneStructList.DoneStruct]){ 76 let doneStructList = DoneStructList(list: list) 77 guard let data = serialize(doneStructList: doneStructList)else{ 78 return 79 } 80 UserDefaults.standard.setValue(data, forKeyPath: "DoneStructList") 81 } 82 83 //UserDefaultsから取得 84 private func getValue() -> [DoneStructList.DoneStruct]? { 85 guard let data = UserDefaults.standard.data(forKey: "DoneStructList")else 86 {return nil} 87 return processJson(data: data) 88 } 89 90//以下ハートをタップしたら色が変わる、ラベルに数字が反映される。 91 92 @IBAction func heart1Tapped(_ sender: Any) { 93 94 switch rate { 95 case 1: 96 rate = 0 97 98 heart1.setImage(heartEmpty, for:UIControl.State() ) 99 heart2.setImage(heartEmpty, for:UIControl.State() ) 100 heart3.setImage(heartEmpty, for:UIControl.State() ) 101 heart4.setImage(heartEmpty, for:UIControl.State() ) 102 heart5.setImage(heartEmpty, for:UIControl.State() ) 103 104 105 default: 106 rate = 1 107 108 heart1.setImage(heartFill, for:UIControl.State() ) 109 heart2.setImage(heartEmpty, for:UIControl.State() ) 110 heart3.setImage(heartEmpty, for:UIControl.State() ) 111 heart4.setImage(heartEmpty, for:UIControl.State() ) 112 heart5.setImage(heartEmpty, for:UIControl.State() ) 113 114 } 115 116 Label.text = String(rate) 117 } 118 119 @IBAction func heart2Tapped(_ sender: Any) { 120 121 //ボタンをタップした時の動作 122 rate = 2 123 124 heart1.setImage(heartFill, for:UIControl.State() ) 125 heart2.setImage(heartFill, for:UIControl.State() ) 126 heart3.setImage(heartEmpty, for:UIControl.State() ) 127 heart4.setImage(heartEmpty, for:UIControl.State() ) 128 heart5.setImage(heartEmpty, for:UIControl.State() ) 129 130 Label.text = String(rate) 131 132 } 133 134 @IBAction func heart3Tapped(_ sender: Any) { 135 136 rate = 3 137 138 heart1.setImage(heartFill, for:UIControl.State() ) 139 heart2.setImage(heartFill, for:UIControl.State() ) 140 heart3.setImage(heartFill, for:UIControl.State() ) 141 heart4.setImage(heartEmpty, for:UIControl.State() ) 142 heart5.setImage(heartEmpty, for:UIControl.State() ) 143 144 Label.text = String(rate) 145 146 } 147 148 @IBAction func heart4Tapped(_ sender: Any) { 149 150 rate = 4 151 152 heart1.setImage(heartFill, for:UIControl.State() ) 153 heart2.setImage(heartFill, for:UIControl.State() ) 154 heart3.setImage(heartFill, for:UIControl.State() ) 155 heart4.setImage(heartFill, for:UIControl.State() ) 156 heart5.setImage(heartEmpty, for:UIControl.State() ) 157 158 Label.text = String(rate) 159 160 } 161 162 163 @IBAction func heart5Tapped(_ sender: Any) { 164 165 rate = 5 166 167 heart1.setImage(heartFill, for:UIControl.State() ) 168 heart2.setImage(heartFill, for:UIControl.State() ) 169 heart3.setImage(heartFill, for:UIControl.State() ) 170 heart4.setImage(heartFill, for:UIControl.State() ) 171 heart5.setImage(heartFill, for:UIControl.State() ) 172 173 Label.text = String(rate) 174 175 }
//NextViewControllerで保存した値を以下のViewControllerで使用したい。 class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource { //いったん文字を入れておく。ここにNextViewControllerで保存したtodoを反映させたい。rate==1のときに入力したテキスト(todo)をheart1へ入れる、rate==2のときに入力したテキスト(todo)をheart2へ入れるという形でいれたい。 let heart1 = ["ご飯を食べる"] let heart2 = ["夜更かし","ご飯を食べる"] let heart3 = ["片付けする","ご飯を食べる"] let heart4 = ["タバコを吸う","散歩する","サウナに行く","家で半身浴"] let heart5 = ["温泉に行く","服を買いに行く"] let sectionTitles = ["♡1","♡2","♡3","♡4","♡5"] @IBOutlet weak var tableView: UITableView! override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. tableView.delegate = self tableView.dataSource = self } //5つのセクションを用意する func numberOfSections(in tableView: UITableView) -> Int { return 5 } //sectionTitlesの数だけセクションを用意する func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { return sectionTitles[section] } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { if section == 0{ return heart1.count }else if section == 1{ return heart2.count }else if section == 2{ return heart3.count }else if section == 3{ return heart4.count }else if section == 4{ return heart5.count }else{ return 0 } } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "Cell",for: indexPath) if indexPath.section == 0 { cell.textLabel?.text =heart1[indexPath.row] }else if indexPath.section == 1{ cell.textLabel?.text = heart2[indexPath.row] }else if indexPath.section == 2{ cell.textLabel?.text = heart3[indexPath.row] }else if indexPath.section == 3{ cell.textLabel?.text = heart4[indexPath.row] }else if indexPath.section == 4{ cell.textLabel?.text = heart5[indexPath.row] } return cell } @IBAction func AddButton(_ sender: Any) { performSegue(withIdentifier: "next", sender: nil) } }
試したこと
let heart1 = UserDefaults.standard.data(forKey:"DoneStructList")!.filter {$0.rate==1 }
→ これを入れるとエラーが出てしまいます。
→rate==1のときに入力したテキスト(todo)をheart1へ入れたい
let heart2 = ["夜更かし","ご飯を食べる"]
→rate==2のときに入力したテキスト(todo)をheart2へ入れたい
let heart3 = ["片付けする","ご飯を食べる"]
** →rate==3のときに入力したテキスト(todo)をheart3へ入れたい**
let heart4 = ["タバコを吸う","散歩する","サウナに行く","家で半身浴"]
→rrate==4のときに入力したテキスト(todo)をheart4へ入れたい
let heart5 = ["温泉に行く","服を買いに行く"]
→rate==5のときに入力したテキスト(todo)をheart5へ入れたい
NextViewControllerで保存したStructをViewControllerで使いたいのですが、
どのように実装すればいいでしょうか。
回答1件
あなたの回答
tips
プレビュー