前提・実現したいこと
メモアプリを作成中ですが、エラーが解決できずに困っています。
coreDataを使ってセクション分けをしたいです。
発生している問題・エラーメッセージ
Thread 1: signal SIGABRT //デバッグメッセージ Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'keypath company not found in entity <NSSQLEntity Memo id=1>'
##メモアプリの概要
就活生用のエントリーシートメモアプリを作成しています。
保存するデータは
- メモのタイトル
- 企業名
- 提出期限名
- メモテキスト
- テキストの文字数
- 作成日時
です。
この中の企業名companyを使ってセクション分けをしたいです。
該当のソースコード
swift
1 2import UIKit 3import CoreData 4 5 6class MemoTableViewController: UITableViewController, UINavigationControllerDelegate, NSFetchedResultsControllerDelegate { 7 8 //配列作成(coreData) for tableView 9 var memoData:[Memo] = [] 10 11 var fetchedResultsController: NSFetchedResultsController<NSFetchRequestResult>! 12 13 let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext 14 15 var fetchedResultController:NSFetchedResultsController<NSFetchRequestResult>! 16 17 override func viewDidLoad() { 18 super.viewDidLoad() 19 20 // 編集ボタンを左上に配置 21 navigationItem.leftBarButtonItem = editButtonItem 22 editButtonItem.tintColor = UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0) 23 24 //編集中のセル選択を許可 25 tableView.allowsSelectionDuringEditing = true 26 27 tableView.reloadData() 28 } 29 30 override func viewWillAppear(_ animated: Bool) { 31 super.viewWillAppear(animated) 32 getData() 33 //配列が追加した後もういちどデータをリロードさせる 34 tableView.reloadData() 35 fetchedResultsController = createFetchedResultsController() 36 37 } 38 39 func getData() { 40 // データ保存時と同様にcontextを定義 41 let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext 42 43 do { 44 // CoreDataからデータをfetchしてtasksに格納 45 let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Memo") 46 fetchRequest.returnsObjectsAsFaults = false 47 48 memoData = try context.fetch(fetchRequest) as! [Memo] 49 50 } catch { 51 print("Fetching Failed.") 52 } 53 } 54 func createFetchedResultsController() -> NSFetchedResultsController<NSFetchRequestResult> { 55 let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Memo") 56 fetchRequest.returnsObjectsAsFaults = false 57 58 //セクションをcompanyごとにまず並び替える 59 fetchRequest.sortDescriptors = [ 60 NSSortDescriptor(key: "company", ascending: true) 61 ] 62 63 let entity = NSEntityDescription.entity(forEntityName: "Memo", in: context) 64 fetchRequest.entity = entity 65 //ソートキーの指定。セクションが存在する場合セクションに対応した属性を必ず最初に指定する 66 let companySortDescriptor = NSSortDescriptor(key: "company", ascending: true) 67 //セクション内は作成日時順 68 let dataSortDescriptor = NSSortDescriptor(key: "createdAt", ascending: true) 69 fetchRequest.sortDescriptors = [companySortDescriptor, dataSortDescriptor] 70 71 //セクションの名前として"publisher"を指定(fetchRequestの初期化) 72 let fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: context, sectionNameKeyPath: "company", cacheName: nil) 73 fetchedResultsController.delegate = self 74 75 do { 76 try fetchedResultsController.performFetch() 77 } catch { 78 abort() 79 } 80 return fetchedResultsController 81 } 82 83 // MARK: - Table View 84 func numberOfSectionsInTableView(tableView: UITableView) -> Int { 85 //セクション数を返す 86 return fetchedResultsController.sections?.count ?? 0 87 } 88 89 90 91 func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? { 92 //セクション名を返す 93 let sectionInfo = fetchedResultsController.sections![section] 94 return sectionInfo.name 95 } 96 97// セルの作成 98 func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 99 //セクション内のオブジェクトの数を返す 100 let sectionInfo = fetchedResultsController.sections![section] 101 return sectionInfo.numberOfObjects 102 } 103 104 //セルの作成 rowは何行目か 105 override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 106 let cell = tableView.dequeueReusableCell(withIdentifier: "MemoTitleTableViewCell", for: indexPath) 107 configureCell(cell: cell, object: fetchedResultsController.object(at: indexPath)) 108 return cell 109 110 } 111 112 func configureCell(cell: UITableViewCell, object: AnyObject) { 113 let memo = object as! Memo 114 cell.textLabel?.text = memo.title 115 cell.detailTextLabel?.text = memo.memoNum 116 } 117 118 119 //セルの削除 120 override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { 121 let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext 122 123 if editingStyle == .delete { 124 // 削除したいデータのcategoryとnameを取得 125 let deletedMemoData = memoData[indexPath.row] 126 127 do { 128 context.delete(deletedMemoData) 129 memoData.remove(at: indexPath.row) 130 } catch { 131 print("Fetching Failed.") 132 } 133 134 // 削除したあとのデータを保存する 135 (UIApplication.shared.delegate as! AppDelegate).saveContext() 136 137 // 削除後の全データをfetchする 138 getData() 139 } 140 // taskTableViewを再読み込みする 141 tableView.reloadData() 142 } 143 144 //セルを選択した時に実行 145 override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 146 self.performSegue(withIdentifier: "showDetail", sender: self) 147 } 148 149//編集 150 override func setEditing(_ editing: Bool, animated: Bool) { 151 super.setEditing(editing, animated: animated) 152 tableView.isEditing = editing 153 } 154 155//画面遷移で値を引き渡す 156 override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 157 guard let identifier = segue.identifier else { 158 return 159 } 160 switch identifier { 161 case "showDetail": 162 //渡したい値を設定する 163 let indexPath = tableView.indexPathForSelectedRow 164 // segueから遷移先のNavigationControllerを取得(画面遷移) 165 let nc = segue.destination as! UINavigationController 166 // NavigationControllerの一番目のViewControllerが次の画面 167 let vc = nc.topViewController as! DetailViewController 168 // contextをAddTaskViewController.swiftのcontextへ渡す 169 let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext 170 vc.context = context 171 172 //indexPathがnilでないことを確認し、選択した行のデータを引きわたす 173 174 if let indexPath = indexPath{ 175 vc.detailData = self.memoData[indexPath.row] 176 } 177 178 179 default: 180 fatalError("Unknow segue: (identifier)") 181 } 182 } 183} 184 185
ちなみにエラー解決のために思考錯誤中に、subclassのデータも作成しました
//Memo+CoreDataClass.swift @objc(Memo) public class Memo: NSManagedObject { @NSManaged public var company: String? @NSManaged public var createdAt: NSDate? @NSManaged public var memoDate: String? @NSManaged public var memoNum: String? @NSManaged public var memoText: String? @NSManaged public var title: String? @objc var sectionDate: String { let dateFormatter = DateFormatter() dateFormatter.locale = NSLocale(localeIdentifier: "en_US") as Locale! dateFormatter.dateFormat = "yyyy/MM/dd" return dateFormatter.string(from: self.createdAt! as Date) } }
//Memo+CoreDataProperties.swift extension Memo { @nonobjc public class func fetchRequest() -> NSFetchRequest<Memo> { return NSFetchRequest<Memo>(entityName: "Memo") } @NSManaged public var company: String? @NSManaged public var createdAt: NSDate? @NSManaged public var memoDate: String? @NSManaged public var memoNum: String? @NSManaged public var memoText: String? @NSManaged public var title: String? }
回答3件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。