前提・実現したいこと
todoとtimerを組み合わせたアプリを作成しています。
登録したtodoに対してかかった時間を記録して、別の画面のtableViewで
todoを実施した日付でセクションを分けて表示させたいです。
発生している問題・エラーメッセージ
自作したサンプルデータを使ってtableViewに表示させることはできたのですが、
UserDefaultsを使ってtodoや時間を保存して受け渡そうとしたときに
取り出されるデータが空になってしまいます。
受け渡したいデータは、以下の4つで、これらを格納するカスタムクラスをUserDefaultsで取り扱いたいです。
1.todo : String
2.time1 : Int
3.time2 : Int
4.date : Date
該当のソースコード
swift
1import Foundation 2 3class Content:NSObject, NSCoding { 4 5 let todo: String 6 let time1: Int 7 let time2: Int 8 let date: Date 9 10 init(todo:String, time1:Int, time2:Int, date:Date) { 11 self.todo = todo 12 self.time1 = time1 13 self.time2 = time2 14 self.date = date 15 } 16 17 func encode(with aCoder: NSCoder) { 18 aCoder.encode(self.todo, forKey: "todo") 19 aCoder.encode(self.estimate, forKey: "time1") 20 aCoder.encode(self.actual, forKey: "time2") 21 aCoder.encode(self.date, forKey: "date") 22 } 23 24 required init?(coder aDecoder: NSCoder) { 25 todo = aDecoder.decodeObject(forKey: "todo") as! String 26 time1 = aDecoder.decodeInteger(forKey: "time1") 27 time2 = aDecoder.decodeInteger(forKey: "time2") 28 date = aDecoder.decodeObject(forKey: "date") as! Date 29 } 30}
swift
1import UIKit 2 3class ViewController: UIViewController, UITextFieldDelegate, UIPickerViewDelegate, UIPickerViewDataSource { 4 5 // 保存するデータのオブジェクトとそれを格納する配列を用意 6 var content = [Content]() 7 var contents = [[Content]]() 8 9 10 ~~~中略~~~ 11 12 13 // doneボタンをクリックした時の処理 14 @IBAction func clickDoneButton(_ sender: Any) { 15 timer.invalidate() 16 17 let todoString:String = todo.text! 18 var time1Int:Int = Int() 19 var time2Int:Int = Int() 20 let now:Date = Date() 21 22 let index = timePickerOption.firstIndex(of: timeLabel.text!) 23 time1Int = convertedTimePickerOption[index!] 24 time2Int = time1Int - count 25 26 // done!押下時の時間を"yyyy/mm/dd"に変換する 27 let f = DateFormatter() 28 f.timeStyle = .none 29 f.dateStyle = .medium 30 f.locale = Locale(identifier: "ja_JP") 31 f.dateFormat = "yyyy/MM/dd" 32 let s = f.string(from: now) 33 34 // contentに書き込み、contentsにappend 35 content = [Content(todo: todoString, time1: time1Int, time2: time2Int, date: f.date(from: s)!)] 36 contents.append(content) 37 38 // UserDefaultsに保存 39 let encodedContents = try? NSKeyedArchiver.archivedData(withRootObject: contents, requiringSecureCoding: false) 40 UserDefaults.standard.set(encodedContents, forKey: "contents") 41 UserDefaults.standard.synchronize() 42 43 // segueでRecordVCに遷移する 44 performSegue(withIdentifier: "record", sender: nil) 45 46 47 }
swift
1 override func viewDidLoad() { 2 super.viewDidLoad() 3 4 recordTableView.delegate = self 5 recordTableView.dataSource = self 6 7 prepare() 8 } 9 10 private func prepare() { 11 // 日付を用意して、"yyyy/MM/dd"に変換 12 let f = DateFormatter() 13 f.locale = Locale(identifier: "en_US_POSIX") 14 f.dateFormat = "yyyy/MM/dd" 15 16 var contents: [Content]! 17 let contentsData = UserDefaults.standard.object(forKey: "contents") as? Data 18 guard let t = contentsData else { return } 19 let unArchiveData = try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(t) 20 contents = unArchiveData as? [Content] ?? [Content]() 21 22 print(contents!) // -> 結果が空[]になってしまう 23 24 todos = Dictionary(grouping: contents) { content -> Date in 25 return content.date 26 } 27 .reduce(into: [Date: [Content]]()) {dic, tuple in 28 dic[tuple.key] = tuple.value.sorted { $0.date < $1.date } 29 } 30 31 // 日付順を保持するための配列 32 dateOrder = Array(todos.keys).sorted { $0 > $1 } 33 34 } 35
試したこと
SwiftでAttempt to insert non-property list objectが出た時の対処について
swift4でカスタムオブジェクトをNSUserDefaultsに保存・読込する
こちらを参考にUserDefaultsへの保存を試みたのですが、うまく値を取り出せません。
contentsにappendするまでは値を入れられているようなのですが、
UserDefaultsへの保存、取り出しで空になってしまっているように思えます。
使い方が不適切なのでしょうか。
よろしくお願いいたします。
補足情報(FW/ツールのバージョンなど)
xcode Version: 11.1
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/10/16 07:22
2019/10/16 08:15
2019/10/16 08:44