SwiftUI 2.0 / CoreData 2021:无错误,但实体未保存



我有一个使用CoreData在本地存储数据的SwiftUI 2.0应用程序,虽然preview模式可以在内存中写入数据或不(我测试了两者),当我试图将数据保存到CoreData在版本视图中,我没有得到错误消息,但数据没有写入模拟器的sqlite数据文件…我做错了什么?

我有一对多关系中的两个实体:

文章:

<
  • 日期:日期/gh>
  • id: UUID
  • 文本:字符串
  • <
  • 时间戳:日期/gh>
  • 图片:许多关系/目的地/反向post

PostPic:

  • data: BinaryData/Allow External Storage
  • post: toOne关系/目的地post/反向图片

我已经提取了下面的主要文件:MyApp.swift

import SwiftUI
@main
struct MyApp: App {
let persistenceController = PersistenceController.shared
var body: some Scene {
WindowGroup {
MyNavigationView().environment(.managedObjectContext, persistenceController.container.viewContext)
}
}
}

Persistence.swift

import Foundation
import SwiftUI
import CoreData
import CloudKit
struct PersistenceController {
static let shared = PersistenceController()
static var preview: PersistenceController = {
let result = PersistenceController(inMemory: true)
let viewContext = result.container.viewContext
for day in 1...10 {
let newPost = Post(context: viewContext)
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy/MM/dd"
newPost.date = dateFormatter.date(from: "2021/02/(String(format: "%02d", day))")!
newPost.id = UUID()
newPost.text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
newpost.timestamp = Date()
for index in 1...7 {
let newPostPic = PostPic(context: viewContext)
if let image = UIImage(named:newPostPic.filename!) {
newPostPic.data = image.pngData()
}
newPost.addToFiles(newPostPic)
}
}
do {
try viewContext.save()
} catch {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
let nsError = error as NSError
fatalError("Unresolved error (nsError), (nsError.userInfo)")
}
return result
}()
let container: NSPersistentCloudKitContainer
private static var _model: NSManagedObjectModel?
private static func model(name: String) throws -> NSManagedObjectModel {
if _model == nil {
_model = try loadModel(name: name, bundle: Bundle.main)
}
return _model!
}
private static func loadModel(name: String, bundle: Bundle) throws -> NSManagedObjectModel {
guard let modelURL = bundle.url(forResource: name, withExtension: "momd") else {
throw CoreDataError.modelURLNotFound(forResourceName: name)
}
guard let model = NSManagedObjectModel(contentsOf: modelURL) else {
throw CoreDataError.modelLoadingFailed(forURL: modelURL)
}
return model
}
enum CoreDataError: Error {
case modelURLNotFound(forResourceName: String)
case modelLoadingFailed(forURL: URL)
}
init(inMemory: Bool = false) {

container = NSPersistentCloudKitContainer(name: "curum")
if inMemory {
container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
}
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error (error), (error.userInfo)")
}
})
}
}

MyNavigationView.swift

struct MyNavigationView: View {
@Environment(.managedObjectContext) private var viewContext
var body: some View {
NavigationView {
TabView { // tab bar at the bottom of the screen
HomeView()
.tabItem{
Image(systemName: "house.fill")
}.tag(0)
}
.navigationBarTitleDisplayMode(.inline)
.navigationTitle("MyApp")
}
}
}
struct MyNavigationView_Previews: PreviewProvider {
static var previews: some View {
MyNavigationView()
}
}

HomeView.swift

//
//  HomeView.swift
//  curum
//
//  Created by loic on 2021/02/19.
//
import SwiftUI
struct HomeView: View {
var body: some View {
ZStack {
// ...
VStack { // the plus button
Spacer()
HStack {
Spacer()
NavigationLink(destination: EditionView().environment(.managedObjectContext, PersistenceController.preview.container.viewContext)) {
ZStack {
Circle()
.frame(width: 80, height: 80)
Image(systemName: "plus")
.renderingMode(.template)
.font(.system(size: 60, weight: .light))
}
}
.padding(.trailing, 16)
.padding(.bottom, 16)
}
}
}
}
}
struct HomeView_Previews: PreviewProvider {
static var previews: some View {
HomeView().environment(.managedObjectContext, PersistenceController.preview.container.viewContext)
}
}

EditionView.swift

import Foundation
import SwiftUI
import CoreData
struct EditionView: View {
@Environment(.managedObjectContext) private var viewContext
@Environment(.presentationMode) var mode: Binding<PresentationMode>
@State private var postText: String = ""
@State private var postImage: Image = Image("image1")
@State private var showingImagePicker = false
@State private var inputImage: UIImage?

var body: some View {
VStack {
TextEditor(text: $postText)
.lineSpacing(10)
.border(Color.gray)
.padding(.all)
HStack {
Button(action: {
self.showingImagePicker = true
}) {

if (inputImage == nil) {
Text("Pick Image")
} else {
postImage
.resizable()
.renderingMode(.original)
.frame(width: 100, height: 100)
}
}.sheet(isPresented: $showingImagePicker, onDismiss: loadImage) {
ImagePicker(image: self.$inputImage)
}
}
}
.navigationBarBackButtonHidden(true)
.navigationBarItems(leading: Button(action : {
self.mode.wrappedValue.dismiss()
}){
Image(systemName: "xmark")
},
trailing: Button {
let newPost = Post(use: viewContext)
newPost.date = Date()
newPost.id = UUID()
newPost.text = entryText
newPost.timestamp = Date()
let newPostPic = PostPic(use: viewContext)
newPostPic.data = inputImage!.pngData()
newPost.addToFiles(newPostPic)
do {
try viewContext.save()
mode.wrappedValue.dismiss()
} catch {
let nsError = error as NSError
fatalError("Unresolved error (nsError), (nsError.userInfo)")
}
} label: {
Image(systemName: "checkmark.circle.fill")
})
}
func loadImage() {
guard let inputImage = inputImage else { return }
postImage = Image(uiImage: inputImage)
}
}
struct EditionView_Previews: PreviewProvider {
static var previews: some View {
EditionView()
}
}
struct ImagePicker: UIViewControllerRepresentable {
@Environment(.presentationMode) var presentationMode
@Binding var image: UIImage?
class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
let parent: ImagePicker
init(_ parent: ImagePicker) {
self.parent = parent
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
if let uiImage = info[.originalImage] as? UIImage {
parent.image = uiImage
}
parent.presentationMode.wrappedValue.dismiss()
}
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePicker>) -> UIImagePickerController {
let picker = UIImagePickerController()
picker.delegate = context.coordinator
return picker
}
func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext<ImagePicker>) {
}
}

**编辑回复@Tushar Sharma**我忘了添加,我添加了以下扩展到NSManagedObject,以摆脱错误,如在多个nsentitydescriptionclaim NSManagedObject子类:

import Foundation
import CoreData
public extension NSManagedObject {
convenience init(use context: NSManagedObjectContext) {
let name = String(describing: type(of: self))
let entity = NSEntityDescription.entity(forEntityName: name, in: context)!
self.init(entity: entity, insertInto: context)
}
}

对不起,这是一个简单的复制粘贴问题在HomeView.swift文件:

在下一行中,我使用了预览持久性上下文…

NavigationLink(destination: EditionView().environment(.managedObjectContext, PersistenceController.preview.container.viewContext)) {

…而不是使用共享的一:

NavigationLink(destination: EditionView().environment(.managedObjectContext, PersistenceController.shared.container.viewContext)) {

这解决了我的问题!

相关内容

  • 没有找到相关文章

最新更新