前提・実現したいこと
Core DataでBinary Dataを用いた状況で
Canvasのpreviewを表示したい
Binary Dataを使わなければ表示できるが、使うとエラーになる。
発生している問題・エラーメッセージ
"Persistent store migration failed, missing mapping model." →再起動や触れているうちに上記は出なくなり、以下が出るようになりました。 "Fatal error: Unexpectedly found nil while unwrapping an Optional value"
該当のソースコード
Swift5.4 ios14.5 Xcode12.5
Core Dataで以下のEntityを作成 ItemEntity name:String detailArray:Binary Data
detailArrayには独自クラス:Detailの配列を格納したい。Detailクラスは次の通り。
import Foundation public class Detail:NSObject,NSCoding { var date: Date var state: Int = 0 // 1,2,3,4 // イニシャライザ init(date:Date,state:Int){ self.date = date self.state = state } // NSCording型で必要なもの public func encode(with coder: NSCoder) { coder.encode(self.date, forKey: "date") coder.encode(self.state, forKey: "state") } // NSCording型で必要なもの public required init?(coder: NSCoder) { self.date = coder.decodeObject(forKey: "date") as! Date self.state = coder.decodeObject(forKey: "state") as! Int } }
Persistence.swiftで初期値を入れておかないとPreviewでエラーになるため以下を設定
struct PersistenceController { static let shared = PersistenceController() static var preview: PersistenceController = { AttributeSecureTransformer.register() let result = PersistenceController(inMemory: true) let viewContext = result.container.viewContext do { let newItem = ItemEntity(context: viewContext) newItem.name = "アイテムネーム1" // 問題と予測している箇所--ここから let detail1:Detail = Detail(date: Date(), state: 2) let entity2:Detail = Detail(date: Date(), state: 4) let resultsData: Data = try NSKeyedArchiver.archivedData( withRootObject:[detail1, detail2], requiringSecureCoding: false) as Data newItem.detailArray = resultsData // 問題と予測している箇所--ここまで } catch let error { print(error.localizedDescription) } do { try viewContext.save() } catch { 省略 } return result }() let container: NSPersistentContainer init(inMemory: Bool = false) { 省略 }
[追記]
表示は以下DetailViewで実施。
前提
親画面NameListViewにItemEntity.nameを表示し、タップしたら
子画面DetailViewにItemEntity.detailArrayのリストを表示したい。
import SwiftUI import CoreData struct DetailView: View { @ObservedObject var oneItemEntity:ItemEntity func getDetailList() -> [Detail] { var detailArray: [Detail] = [] do { detailArray = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(oneItemEntity.detailArray!) as! [Detail] } catch let error { // **** ここでエラー Unexpectedly found nil while unwrapping an Optional value**** print(error.localizedDescription) } return detailArray } var body: some View { VStack(alignment: .leading) { HStack { Group{ Text("state:") Text("(getDetailList()[0].state)") .font(.title) } } Group{ Spacer() } } } } struct DetailView_Previews: PreviewProvider { static var context = PersistenceController.preview.container.viewContext static var previews: some View { let itemEntity = ItemEntity.init(context: context) return Group { DetailView( oneItemEntity: itemEntity ) } .previewLayout(.fixed(width: 800, height: 70)) } }
参考:親画面NameListView
import SwiftUI struct NameListView: View { @Environment(.managedObjectContext) private var context @FetchRequest( entity: ItemEntity.entity(), sortDescriptors: [ NSSortDescriptor( keyPath: \ItemEntity.name, ascending: true ) ], predicate: nil ) private var items: FetchedResults<ItemEntity> var body: some View { 省略 Core Data のItemEntityについて、detailArrayを定義する前は nameの表示は可能でした。 } } struct NameListView_Previews: PreviewProvider { static var previews: some View { NameListView() .environment( .managedObjectContext, PersistenceController.preview.container.viewContext) } }
試したこと
・ItemEntityを使用しない画面でpreviewを試した際、
上記のままではエラー発生。「問題と予測している箇所」をコメントアウトすればpreviewできる
[追記]
上記は勘違いでした。
ItemEntityを使用しない画面は、preview可能です。
・Transformableというので最初実現しようとしたが断念
回答1件
あなたの回答
tips
プレビュー